diff --git a/wire/modules/Image/ImageSizerEngineAnimatedGif/ImageSizerEngineAnimatedGif.module b/wire/modules/Image/ImageSizerEngineAnimatedGif/ImageSizerEngineAnimatedGif.module new file mode 100755 index 00000000..e052bcaa --- /dev/null +++ b/wire/modules/Image/ImageSizerEngineAnimatedGif/ImageSizerEngineAnimatedGif.module @@ -0,0 +1,357 @@ + 'Animated GIF Image Sizer', + 'version' => 1, + 'summary' => "Upgrades image manipulations for animated GIFs.", + 'author' => 'Horst Nogajski', + ); + } + + /** + * Class constructor + * + */ + public function __construct() { + parent::__construct(); + $this->set('enginePriority', 9); // use a late priority so that optional other installed engines get the job (first) if they support animated gifs + } + + /** + * Get valid image source formats + * + * @return array + * + */ + protected function validSourceImageFormats() { + return array('GIF'); + } + + /** + * Get valid target image formats + * + * @return array + * + */ + protected function validTargetImageFormats() { + return $this->validSourceImageFormats(); + } + + /** + * Is GD supported? + * + * @param string $action + * @return bool + * + */ + public function supported($action = 'imageformat') { + // first we check parts that are mandatory for all $actions + if(!function_exists('gd_info')) return false; + + // and if it passes the mandatory requirements, we check particularly aspects here + switch($action) { + case 'imageformat': + // compare current imagefile infos fetched from ImageInspector + $requested = $this->getImageInfo(false); + switch($requested) { + case 'gif-anim': + case 'gif-trans-anim': + return true; + default: + return false; + } + break; + + case 'install': + return true; + + default: + return false; + } + } + + /** + * Process the image resize + * + * Processing is as follows: + * 1. first do a check if the given image(type) can be processed, if not do an early return false + * 2. than (try) to process all required steps, if one failes, return false + * 3. if all is successful, finally return true + * + * @param string $srcFilename Source file + * @param string $dstFilename Destination file + * @param int $fullWidth Current width + * @param int $fullHeight Current height + * @param int $finalWidth Requested final width + * @param int $finalHeight Requested final height + * @return bool True if successful, false if not + * @throws WireException + * + */ + protected function processResize($srcFilename, $dstFilename, $fullWidth, $fullHeight, $finalWidth, $finalHeight) { + $this->modified = false; + if(isset($this->info['bits'])) $this->imageDepth = $this->info['bits']; + $this->imageFormat = strtoupper(str_replace('image/', '', $this->info['mime'])); + + if(!in_array($this->imageFormat, $this->validSourceImageFormats())) { + throw new WireException(sprintf($this->_("loaded file '%s' is not in the list of valid images"), basename($dstFilename))); + } + + require_once(__DIR__ . '/gif_encoder.php'); + require_once(__DIR__ . '/gif_decoder.php'); + + $this->setTimeLimit(120); + + // if extra crop manipulation is requested, it is processed first + if(is_array($this->cropExtra) && 4 == count($this->cropExtra)) { // crop before resize + list($cropX, $cropY, $cropWidth, $cropHeight) = $this->cropExtra; + $bg = null; + $gif = new ISEAG_GIFDecoder(file_get_contents($srcFilename)); + $originalFramesMeta = $gif->GIFGetFramesMeta(); + if(count($originalFramesMeta) <= 0) return false; + $this->meta = array( + 'delays' => $gif->GIFGetDelays(), + 'loops' => $gif->GIFGetLoop(), + 'disposal' => $gif->GIFGetDisposal(), + 'tr' => $gif->GIFGetTransparentR(), + 'tg' => $gif->GIFGetTransparentG(), + 'tb' => $gif->GIFGetTransparentB(), + 'trans' => (0 == $gif->GIFGetTransparentI() ? false : true) + ); + $originalFrames = $gif->GIFGetFrames(); + $newFrames = array(); + foreach($originalFrames as $k => $v) { + $frame = @imagecreatefromstring($v); + if(!is_resource($frame)) continue; + if(!is_resource($bg)) { + $bg = imagecreatetruecolor($fullWidth, $fullHeight); + $this->prepareGDimage($bg); + } + $srcX = 0; + $srcY = 0; + $srcW = imagesx($frame); + $srcH = imagesy($frame); + $dstX = $originalFramesMeta[$k]['left']; + $dstY = $originalFramesMeta[$k]['top']; + $dstW = $originalFramesMeta[$k]['width']; + $dstH = $originalFramesMeta[$k]['height']; + imagecopy($bg, $frame, $dstX, $dstY, $srcX, $srcY, $srcW, $srcH); + $newimg = imagecreatetruecolor($cropWidth, $cropHeight); + $this->prepareGDimage($newimg); + imagecopy($newimg, $bg, 0, 0, $cropX, $cropY, $cropWidth, $cropHeight); + array_push($newFrames, $newimg); + $originalFrames[$k] = null; + } + if(count($newFrames) > 0) { + $frames = array(); + foreach($newFrames as $nf) { + if(!is_resource($nf)) continue; + ob_start(); + imagegif($nf); + $gifdata = ob_get_clean(); + array_push($frames, $gifdata); + @imagedestroy($nf); + } + $gifmerge = new ISEAG_GIFEncoder( + $frames, + $this->meta['delays'], + $this->meta['loops'], + $this->meta['disposal'], + $this->meta['tr'], $this->meta['tg'], $this->meta['tb'], + 'bin' + ); + $result = false === fwrite(fopen($srcFilename, 'wb'), $gifmerge->GetAnimation()) ? false : true; + if($result) { + $fullWidth = $cropWidth; + $fullHeight = $cropHeight; + $this->image = array('width' => $fullWidth, 'height' => $fullHeight); + } + } else { + // $result = false; + } + if(isset($bg) && is_resource($bg)) @imagedestroy($bg); + if(isset($frame) && is_resource($frame)) @imagedestroy($frame); + if(isset($newimg) && is_resource($newimg)) @imagedestroy($newimg); + unset($gif, $gifmerge, $originalFrames, $originalFramesMeta, $newFrames, $cropHeight, $cropWidth, $cropX, $cropY, $dstH, $dstW, $dstX, $dstY, $frames, $nf, $srcH, $srcW, $srcX, $srcY); + $this->meta = null; + } + + // regular resize / crop manipulation starts here + $bgX = $bgY = 0; + $bgWidth = $fullWidth; + $bgHeight = $fullHeight; + $resizemethod = $this->getResizeMethod($bgWidth, $bgHeight, $finalWidth, $finalHeight, $bgX, $bgY); + if(0 == $resizemethod) return true; // if same size or disallowed greater size is requested, we stop here and leave the original copy as is + + $gif = new ISEAG_GIFdecoder(file_get_contents($srcFilename)); + $originalFramesMeta = $gif->GIFGetFramesMeta(); + if(count($originalFramesMeta) <= 0) return false; + $this->meta = array( + 'delays' => $gif->GIFGetDelays(), + 'loops' => $gif->GIFGetLoop(), + 'disposal' => $gif->GIFGetDisposal(), + 'tr' => $gif->GIFGetTransparentR(), + 'tg' => $gif->GIFGetTransparentG(), + 'tb' => $gif->GIFGetTransparentB(), + 'trans' => (0 == $gif->GIFGetTransparentI() ? false : true) + ); + $originalFrames = $gif->GIFGetFrames(); + $newFrames = array(); + + if(2 == $resizemethod) { // 2 = resize with aspect ratio + $bg = null; + // $ratio = 1.0; + $ratio_w = $fullWidth / $finalWidth; + $ratio_h = $fullHeight / $finalHeight; + $ratio = ($ratio_h > $ratio_w ? $ratio_h : $ratio_w); + foreach($originalFrames as $k => $v) { + $frame = @imagecreatefromstring($v); + if(!is_resource($frame)) continue; + $newimg = imagecreatetruecolor($finalWidth, $finalHeight); + $this->prepareGDimage($newimg); + if(is_resource($bg)) { + imagecopy($newimg, $bg, 0, 0, 0, 0, $finalWidth, $finalHeight); + } + $srcX = 0; + $srcY = 0; + $srcW = imagesx($frame); + $srcH = imagesy($frame); + $dstX = floor($originalFramesMeta[$k]['left'] / $ratio); + $dstY = floor($originalFramesMeta[$k]['top'] / $ratio); + $dstW = ceil($originalFramesMeta[$k]['width'] / $ratio); + $dstH = ceil($originalFramesMeta[$k]['height'] / $ratio); + imagecopyresampled($newimg, $frame, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + array_push($newFrames, $newimg); + if(!is_resource($bg)) { + $bg = imagecreatetruecolor($finalWidth, $finalHeight); + $this->prepareGDimage($bg); + } + imagecopy($bg, $newimg, 0, 0, 0, 0, $finalWidth, $finalHeight); + $originalFrames[$k] = null; + } + } + + if(4 == $resizemethod) { // 4 = resize and crop from center with aspect ratio + $bg = null; + // $ratio = 1.0; + $ratio_w = $fullWidth / $bgWidth; + $ratio_h = $fullHeight / $bgHeight; + $ratio = ($ratio_h > $ratio_w ? $ratio_h : $ratio_w); + foreach($originalFrames as $k => $v) { + $frame = @imagecreatefromstring($v); + if(!is_resource($frame)) continue; + $newimg = imagecreatetruecolor($bgWidth, $bgHeight); + $this->prepareGDimage($newimg); + if(is_resource($bg)) { + imagecopy($newimg, $bg, 0, 0, 0, 0, $bgWidth, $bgHeight); + } + $srcX = 0; + $srcY = 0; + $srcW = imagesx($frame); + $srcH = imagesy($frame); + $dstX = floor($originalFramesMeta[$k]['left'] / $ratio); + $dstY = floor($originalFramesMeta[$k]['top'] / $ratio); + $dstW = ceil($originalFramesMeta[$k]['width'] / $ratio); + $dstH = ceil($originalFramesMeta[$k]['height'] / $ratio); + imagecopyresampled($newimg, $frame, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + if(!is_resource($bg)) { + $bg = imagecreatetruecolor($bgWidth, $bgHeight); + $this->prepareGDimage($bg); + } + imagecopy($bg, $newimg, 0, 0, 0, 0, $bgWidth, $bgHeight); + $newimg = imagecreatetruecolor($finalWidth, $finalHeight); + $this->prepareGDimage($newimg); + imagecopy($newimg, $bg, 0, 0, $bgX, $bgY, $finalWidth, $finalHeight); + array_push($newFrames, $newimg); + $originalFrames[$k] = null; + } + } + + if(count($newFrames) > 0) { + $frames = array(); + foreach($newFrames as $nf) { + if(!is_resource($nf)) continue; + ob_start(); + imagegif($nf); + $gifdata = ob_get_clean(); + array_push($frames, $gifdata); + @imagedestroy($nf); + } + $gifmerge = new ISEAG_GIFEncoder( + $frames, + $this->meta['delays'], + $this->meta['loops'], + $this->meta['disposal'], + $this->meta['tr'], $this->meta['tg'], $this->meta['tb'], + 'bin' + ); + $result = false === fwrite(fopen($dstFilename, 'wb'), $gifmerge->GetAnimation()) ? false : true; + } else { + $result = false; + } + + if(isset($bg) && is_resource($bg)) @imagedestroy($bg); + if(isset($frame) && is_resource($frame)) @imagedestroy($frame); + if(isset($newimg) && is_resource($newimg)) @imagedestroy($newimg); + + if(!$result) { + return false; + } + + $this->modified = true; + return true; + } + + /** + * Helper for transparent background preparation + * + * @param resource $gdimage by reference $gdimage + * @return void + * + */ + protected function prepareGDimage(&$gdimage) { + if(!$this->meta['trans']) return; + $transparentNew = imagecolorallocate($gdimage, $this->meta['tr'], $this->meta['tg'], $this->meta['tb']); + $transparentNewIndex = imagecolortransparent($gdimage, $transparentNew); + imagefill($gdimage, 0, 0, $transparentNewIndex); + } + + + /** + * Module install + * + * @throws WireException + * + */ + public function ___install() { + if(!$this->supported('install')) { + throw new WireException("This module requires that you have PHP's GD image library bundled or installed"); + } + } + +} diff --git a/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_decoder.php b/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_decoder.php new file mode 100755 index 00000000..d3cc0baa --- /dev/null +++ b/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_decoder.php @@ -0,0 +1,352 @@ +GIF_stream = $GIF_pointer; + + ISEAG_GIFDecoder::GIFGetByte ( 6 ); + ISEAG_GIFDecoder::GIFGetByte ( 7 ); + + $this->GIF_screen = $this->GIF_buffer; + $this->GIF_colorF = $this->GIF_buffer [ 4 ] & 0x80 ? 1 : 0; + $this->GIF_sorted = $this->GIF_buffer [ 4 ] & 0x08 ? 1 : 0; + $this->GIF_colorC = $this->GIF_buffer [ 4 ] & 0x07; + $this->GIF_colorS = 2 << $this->GIF_colorC; + + if ( $this->GIF_colorF == 1 ) { + ISEAG_GIFDecoder::GIFGetByte ( 3 * $this->GIF_colorS ); + $this->GIF_global = $this->GIF_buffer; + } + for ( $cycle = 1; $cycle; ) { + if ( ISEAG_GIFDecoder::GIFGetByte ( 1 ) ) { + switch ( $this->GIF_buffer [ 0 ] ) { + case 0x21: + ISEAG_GIFDecoder::GIFReadExtensions ( ); + break; + case 0x2C: + ISEAG_GIFDecoder::GIFReadDescriptor ( ); + break; + case 0x3B: + $cycle = 0; + break; + } + } + else { + $cycle = 0; + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadExtension ( ) + :: + */ + function GIFReadExtensions ( ) { + ISEAG_GIFDecoder::GIFGetByte ( 1 ); + if ( $this->GIF_buffer [ 0 ] == 0xff ) { + for ( ; ; ) { + ISEAG_GIFDecoder::GIFGetByte ( 1 ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + ISEAG_GIFDecoder::GIFGetByte ( $u ); + if ( $u == 0x03 ) { + $this->GIF_anloop = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 ); + } + } + } + else { + for ( ; ; ) { + ISEAG_GIFDecoder::GIFGetByte ( 1 ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + ISEAG_GIFDecoder::GIFGetByte ( $u ); + if ( $u == 0x04 ) { + $buf4 = count($this->GIF_buffer) >= 5 ? $this->GIF_buffer [ 4 ] : 0; + if ( $buf4 & 0x80 ) { + $this->GIF_dispos [ ] = ( $this->GIF_buffer [ 0 ] >> 2 ) - 1; + } + else { + $this->GIF_dispos [ ] = ( $this->GIF_buffer [ 0 ] >> 2 ) - 0; + } + $this->GIF_delays [ ] = ( $this->GIF_buffer [ 1 ] | $this->GIF_buffer [ 2 ] << 8 ); + if ( $this->GIF_buffer [ 3 ] ) { + $this->GIF_TransparentI = $this->GIF_buffer [ 3 ]; + } + } + } + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFReadDescriptor ( ) + :: + */ + function GIFReadDescriptor ( ) { + $GIF_screen = Array ( ); + + ISEAG_GIFDecoder::GIFGetByte ( 9 ); + + //xurei - metadata saving + $this->GIF_frames_meta[] = array( + 'left'=>$this->GIF_buffer[0] + ($this->GIF_buffer[1] << 8), + 'top'=>$this->GIF_buffer[2] + ($this->GIF_buffer[3] << 8), + 'width'=>$this->GIF_buffer[4] + ($this->GIF_buffer[5] << 8), + 'height'=>$this->GIF_buffer[6] + ($this->GIF_buffer[7] << 8), + ); + + $GIF_screen = $this->GIF_buffer; + $GIF_colorF = $this->GIF_buffer [ 8 ] & 0x80 ? 1 : 0; + if ( $GIF_colorF ) { + $GIF_code = $this->GIF_buffer [ 8 ] & 0x07; + $GIF_sort = $this->GIF_buffer [ 8 ] & 0x20 ? 1 : 0; + } + else { + $GIF_code = $this->GIF_colorC; + $GIF_sort = $this->GIF_sorted; + } + $GIF_size = 2 << $GIF_code; + $this->GIF_screen [ 4 ] &= 0x70; + $this->GIF_screen [ 4 ] |= 0x80; + $this->GIF_screen [ 4 ] |= $GIF_code; + if ( $GIF_sort ) { + $this->GIF_screen [ 4 ] |= 0x08; + } + + /* + * + * GIF Data Begin + * + */ + if ( $this->GIF_TransparentI ) { + $this->GIF_string = "GIF89a"; + } + else { + $this->GIF_string = "GIF87a"; + } + ISEAG_GIFDecoder::GIFPutByte ( $this->GIF_screen ); + if ( $GIF_colorF == 1 ) { + ISEAG_GIFDecoder::GIFGetByte ( 3 * $GIF_size ); + if ( $this->GIF_TransparentI ) { + $this->GIF_TransparentR = $this->GIF_buffer [ 3 * $this->GIF_TransparentI + 0 ]; + $this->GIF_TransparentG = $this->GIF_buffer [ 3 * $this->GIF_TransparentI + 1 ]; + $this->GIF_TransparentB = $this->GIF_buffer [ 3 * $this->GIF_TransparentI + 2 ]; + } + ISEAG_GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + else { + if ( $this->GIF_TransparentI ) { + $this->GIF_TransparentR = $this->GIF_global [ 3 * $this->GIF_TransparentI + 0 ]; + $this->GIF_TransparentG = $this->GIF_global [ 3 * $this->GIF_TransparentI + 1 ]; + $this->GIF_TransparentB = $this->GIF_global [ 3 * $this->GIF_TransparentI + 2 ]; + } + ISEAG_GIFDecoder::GIFPutByte ( $this->GIF_global ); + } + if ( $this->GIF_TransparentI ) { + $this->GIF_string .= "!\xF9\x04\x1\x0\x0". chr ( $this->GIF_TransparentI ) . "\x0"; + } + $this->GIF_string .= chr ( 0x2C ); + $GIF_screen [ 8 ] &= 0x40; + ISEAG_GIFDecoder::GIFPutByte ( $GIF_screen ); + ISEAG_GIFDecoder::GIFGetByte ( 1 ); + ISEAG_GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + for ( ; ; ) { + ISEAG_GIFDecoder::GIFGetByte ( 1 ); + ISEAG_GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + if ( ( $u = $this->GIF_buffer [ 0 ] ) == 0x00 ) { + break; + } + + /*for ($i=0; $i!=$u; ++$i) + { + $this->GIF_string .= $this->GIF_stream { $this->GIF_bfseek++ }; + }*/ + $this->GIF_string .= substr($this->GIF_stream, $this->GIF_bfseek, $u); + $this->GIF_bfseek += $u; + + //GIFDecoder::GIFGetByte ( $u ); + //GIFDecoder::GIFPutByte ( $this->GIF_buffer ); + } + $this->GIF_string .= chr ( 0x3B ); + /* + * + * GIF Data End + * + */ + $this->GIF_arrays [ ] = $this->GIF_string; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetByte ( $len ) + :: + */ + function GIFGetByte ( $len ) { + $this->GIF_buffer = new \SplFixedArray($len); + + $l = strlen ( $this->GIF_stream ); + for ( $i = 0; $i < $len; $i++ ) { + if ( $this->GIF_bfseek > $l ) { + $this->GIF_buffer->setSize($i); + return 0; + } + $this->GIF_buffer [$i] = ord ( $this->GIF_stream { $this->GIF_bfseek++ } ); + } + return 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFPutByte ( $bytes ) + :: + */ + function GIFPutByte ( $bytes ) { + $out = ''; + foreach ( $bytes as $byte ) { + $out .= chr($byte); + } + $this->GIF_string .= $out; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: PUBLIC FUNCTIONS + :: + :: + :: GIFGetFrames ( ) + :: + */ + function GIFGetFrames ( ) { + return ( $this->GIF_arrays ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetFramesMeta ( ) + :: + :: xurei - returns metadata as an array of arrays + */ + function GIFGetFramesMeta ( ) { + return ( $this->GIF_frames_meta ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetDelays ( ) + :: + */ + function GIFGetDelays ( ) { + return ( $this->GIF_delays ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetLoop ( ) + :: + */ + function GIFGetLoop ( ) { + return ( $this->GIF_anloop ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetDisposal ( ) + :: + */ + function GIFGetDisposal ( ) { + return ( $this->GIF_dispos ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetTransparentR ( ) + :: + */ + function GIFGetTransparentR ( ) { + return ( $this->GIF_TransparentR ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetTransparentG ( ) + :: + */ + function GIFGetTransparentG ( ) { + return ( $this->GIF_TransparentG ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetTransparentB ( ) + :: + */ + function GIFGetTransparentB ( ) { + return ( $this->GIF_TransparentB ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFGetTransparentI ( ) + :: + */ + function GIFGetTransparentI ( ) { + return ( $this->GIF_TransparentI ); + } +} + + diff --git a/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_encoder.php b/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_encoder.php new file mode 100755 index 00000000..c0eb3a60 --- /dev/null +++ b/wire/modules/Image/ImageSizerEngineAnimatedGif/gif_encoder.php @@ -0,0 +1,265 @@ +"Does not supported function for only one image!", + 'ERR01'=>"Source is not a GIF image!", + 'ERR02'=>"Unintelligible flag ", + 'ERR03'=>"Does not make animation from animated GIF source", + ); + + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: ISEAG_GIFEncoder... + :: + */ + function __construct ( + $GIF_src, $GIF_dly, $GIF_lop, $GIF_dis, + $GIF_red, $GIF_grn, $GIF_blu, $GIF_mod + ) { + if ( ! is_array ( $GIF_src ) && ! is_array ( $GIF_dly ) ) { + printf ( "%s: %s", $this->VER, $this->ERR [ 'ERR00' ] ); + exit ( 0 ); + } + $this->LOP = ( $GIF_lop > -1 ) ? $GIF_lop : 0; + + $GIF_dis_out = $GIF_dis; + foreach ($GIF_dis_out as &$dis) + { + $dis = ( $dis > -1 ) ? ( ( $dis < 3 ) ? $dis : 3 ) : 2; + } + + $this->DIS = $GIF_dis_out;//( $GIF_dis > -1 ) ? ( ( $GIF_dis < 3 ) ? $GIF_dis : 3 ) : 2; + /*$this->COL = ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) ? + ( $GIF_red | ( $GIF_grn << 8 ) | ( $GIF_blu << 16 ) ) : -1;*/ + if ( $GIF_red > -1 && $GIF_grn > -1 && $GIF_blu > -1 ) + { + $this->TRANSPARENT_R = $GIF_red & 0xFF; + $this->TRANSPARENT_G = $GIF_grn & 0xFF; + $this->TRANSPARENT_B = $GIF_blu & 0xFF; + } + + //Filling in the buffer + for ( $i = 0; $i < count ( $GIF_src ); $i++ ) { + if ( strToLower ( $GIF_mod ) == "url" ) { + $this->BUF [ ] = fread ( fopen ( $GIF_src [ $i ], "rb" ), filesize ( $GIF_src [ $i ] ) ); + } + else if ( strToLower ( $GIF_mod ) == "bin" ) { + $this->BUF [ ] = $GIF_src [ $i ]; + } + else { + printf ( "%s: %s ( %s )!", $this->VER, $this->ERR [ 'ERR02' ], $GIF_mod ); + exit ( 0 ); + } + if ( substr ( $this->BUF [ $i ], 0, 6 ) != "GIF87a" && substr ( $this->BUF [ $i ], 0, 6 ) != "GIF89a" ) { + printf ( "%s: %d %s", $this->VER, $i, $this->ERR [ 'ERR01' ] ); + exit ( 0 ); + } + for ( $j = ( 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ), $k = TRUE; $k; $j++ ) { + switch ( $this->BUF [ $i ] { $j } ) { + case "!": + if ( ( substr ( $this->BUF [ $i ], ( $j + 3 ), 8 ) ) == "NETSCAPE" ) { + printf ( "%s: %s ( %s source )!", $this->VER, $this->ERR [ 'ERR03' ], ( $i + 1 ) ); + exit ( 0 ); + } + break; + case ";": + $k = FALSE; + break; + } + } + } + ISEAG_GIFEncoder::GIFAddHeader ( ); + for ( $i = 0; $i < count ( $this->BUF ); $i++ ) { + ISEAG_GIFEncoder::GIFAddFrames ( $i, $GIF_dly[$i] ); + } + ISEAG_GIFEncoder::GIFAddFooter ( ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddHeader... + :: + */ + function GIFAddHeader ( ) { + $cmap = 0; + + if ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x80 ) { + $cmap = 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ); + + $this->GIF .= substr ( $this->BUF [ 0 ], 6, 7 ); + $this->GIF .= substr ( $this->BUF [ 0 ], 13, $cmap ); + $this->GIF .= "!\377\13NETSCAPE2.0\3\1" . ISEAG_GIFEncoder::GIFWord ( $this->LOP ) . "\0"; + } + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFrames... + :: + */ + function GIFAddFrames ( $i, $d ) { + + $Locals_str = 13 + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); + + $Locals_end = strlen ( $this->BUF [ $i ] ) - $Locals_str - 1; + $Locals_tmp = substr ( $this->BUF [ $i ], $Locals_str, $Locals_end ); + + $Global_len = 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_len = 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + + $Global_rgb = substr ( $this->BUF [ 0 ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ) ) ); + $Locals_rgb = substr ( $this->BUF [ $i ], 13, + 3 * ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ) ); + + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS[$i] << 2 ) + 0 ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . "\x0\x0"; + + if ( $this->TRANSPARENT_R > -1 && ord ( $this->BUF [ $i ] { 10 } ) & 0x80 ) { + for ( $j = 0; $j < ( 2 << ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ) ); $j++ ) { + if ( + ord ( $Locals_rgb { 3 * $j + 0 } ) == $this->TRANSPARENT_R && + ord ( $Locals_rgb { 3 * $j + 1 } ) == $this->TRANSPARENT_G && + ord ( $Locals_rgb { 3 * $j + 2 } ) == $this->TRANSPARENT_B ) + { + $Locals_ext = "!\xF9\x04" . chr ( ( $this->DIS[$i] << 2 ) ) . + chr ( ( $d >> 0 ) & 0xFF ) . chr ( ( $d >> 8 ) & 0xFF ) . chr ( $j ) . "\x0"; + break; + } + } + } + switch ( $Locals_tmp { 0 } ) { + case "!": + $Locals_img = substr ( $Locals_tmp, 8, 10 ); + $Locals_ext[3] = chr((ord($Locals_ext[3]) & 0xFE) | (ord($Locals_tmp[3]) & 0x01)); + $Locals_tmp = substr ( $Locals_tmp, 18, strlen ( $Locals_tmp ) - 18 ); + break; + case ",": + $Locals_img = substr ( $Locals_tmp, 0, 10 ); + $Locals_tmp = substr ( $Locals_tmp, 10, strlen ( $Locals_tmp ) - 10 ); + break; + } + if ( ord ( $this->BUF [ $i ] { 10 } ) & 0x80 && $this->IMG > -1 ) { + if ( $Global_len == $Locals_len ) { + if ( ISEAG_GIFEncoder::GIFBlockCompare ( $Global_rgb, $Locals_rgb, $Global_len ) ) { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ 0 ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $byte = ord ( $Locals_img { 9 } ); + $byte |= 0x80; + $byte &= 0xF8; + $byte |= ( ord ( $this->BUF [ $i ] { 10 } ) & 0x07 ); + $Locals_img { 9 } = chr ( $byte ); + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_rgb . $Locals_tmp ); + } + } + else { + $this->GIF .= ( $Locals_ext . $Locals_img . $Locals_tmp ); + } + $this->IMG = 1; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFAddFooter... + :: + */ + function GIFAddFooter ( ) { + $this->GIF .= ";"; + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFBlockCompare... + :: + */ + function GIFBlockCompare ( $GlobalBlock, $LocalBlock, $Len ) { + + for ( $i = 0; $i < $Len; $i++ ) { + if ( + $GlobalBlock { 3 * $i + 0 } != $LocalBlock { 3 * $i + 0 } || + $GlobalBlock { 3 * $i + 1 } != $LocalBlock { 3 * $i + 1 } || + $GlobalBlock { 3 * $i + 2 } != $LocalBlock { 3 * $i + 2 } + ) { + return ( 0 ); + } + } + + return ( 1 ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GIFWord... + :: + */ + function GIFWord ( $int ) { + + return ( chr ( $int & 0xFF ) . chr ( ( $int >> 8 ) & 0xFF ) ); + } + /* + ::::::::::::::::::::::::::::::::::::::::::::::::::: + :: + :: GetAnimation... + :: + */ + function GetAnimation ( ) { + return ( $this->GIF ); + } +} diff --git a/wire/modules/ImageSizerEngineIMagick.module b/wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module similarity index 100% rename from wire/modules/ImageSizerEngineIMagick.module rename to wire/modules/Image/ImageSizerEngineIMagick/ImageSizerEngineIMagick.module