00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 class Varien_Image_Adapter_Gd2 extends Varien_Image_Adapter_Abstract
00029 {
00030 protected $_requiredExtensions = Array("gd");
00031 private static $_callbacks = array(
00032 IMAGETYPE_GIF => array('output' => 'imagegif', 'create' => 'imagecreatefromgif'),
00033 IMAGETYPE_JPEG => array('output' => 'imagejpeg', 'create' => 'imagecreatefromjpeg'),
00034 IMAGETYPE_PNG => array('output' => 'imagepng', 'create' => 'imagecreatefrompng'),
00035 IMAGETYPE_XBM => array('output' => 'imagexbm', 'create' => 'imagecreatefromxbm'),
00036 IMAGETYPE_WBMP => array('output' => 'imagewbmp', 'create' => 'imagecreatefromxbm'),
00037 );
00038
00039 public function open($filename)
00040 {
00041 $this->_fileName = $filename;
00042 $this->getMimeType();
00043 $this->_getFileAttributes();
00044 $this->_imageHandler = call_user_func($this->_getCallback('create'), $this->_fileName);
00045 }
00046
00047 public function save($destination=null, $newName=null)
00048 {
00049 $fileName = ( !isset($destination) ) ? $this->_fileName : $destination;
00050
00051 if( isset($destination) && isset($newName) ) {
00052 $fileName = $destination . "/" . $fileName;
00053 } elseif( isset($destination) && !isset($newName) ) {
00054 $info = pathinfo($destination);
00055 $fileName = $destination;
00056 $destination = $info['dirname'];
00057 } elseif( !isset($destination) && isset($newName) ) {
00058 $fileName = $this->_fileSrcPath . "/" . $newName;
00059 } else {
00060 $fileName = $this->_fileSrcPath . $this->_fileSrcName;
00061 }
00062
00063 $destinationDir = ( isset($destination) ) ? $destination : $this->_fileSrcPath;
00064
00065 if( !is_writable($destinationDir) ) {
00066 try {
00067 $io = new Varien_Io_File();
00068 $io->mkdir($destination);
00069 } catch (Exception $e) {
00070 throw new Exception("Unable to write file into directory '{$destinationDir}'. Access forbidden.");
00071 }
00072 }
00073
00074
00075 $isAlpha = false;
00076 $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
00077 if ($isAlpha) {
00078 $this->_fillBackgroundColor($this->_imageHandler);
00079 }
00080 call_user_func($this->_getCallback('output'), $this->_imageHandler, $fileName);
00081 }
00082
00083 public function display()
00084 {
00085 header("Content-type: ".$this->getMimeType());
00086 call_user_func($this->_getCallback('output'), $this->_imageHandler);
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 private function _getCallback($callbackType, $fileType = null, $unsupportedText = 'Unsupported image format.')
00098 {
00099 if (null === $fileType) {
00100 $fileType = $this->_fileType;
00101 }
00102 if (empty(self::$_callbacks[$fileType])) {
00103 throw new Exception($unsupportedText);
00104 }
00105 if (empty(self::$_callbacks[$fileType][$callbackType])) {
00106 throw new Exception('Callback not found.');
00107 }
00108 return self::$_callbacks[$fileType][$callbackType];
00109 }
00110
00111 private function _fillBackgroundColor(&$imageResourceTo)
00112 {
00113
00114 if ($this->_keepTransparency) {
00115 $isAlpha = false;
00116 $transparentIndex = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
00117 try {
00118
00119 if ($isAlpha) {
00120 if (!imagealphablending($imageResourceTo, false)) {
00121 throw new Exception('Failed to set alpha blending for PNG image.');
00122 }
00123 $transparentAlphaColor = imagecolorallocatealpha($imageResourceTo, 0, 0, 0, 127);
00124 if (false === $transparentAlphaColor) {
00125 throw new Exception('Failed to allocate alpha transparency for PNG image.');
00126 }
00127 if (!imagefill($imageResourceTo, 0, 0, $transparentAlphaColor)) {
00128 throw new Exception('Failed to fill PNG image with alpha transparency.');
00129 }
00130 if (!imagesavealpha($imageResourceTo, true)) {
00131 throw new Exception('Failed to save alpha transparency into PNG image.');
00132 }
00133 return $transparentAlphaColor;
00134 }
00135
00136 elseif (false !== $transparentIndex) {
00137 list($r, $g, $b) = array_values(imagecolorsforindex($this->_imageHandler, $transparentIndex));
00138 $transparentColor = imagecolorallocate($imageResourceTo, $r, $g, $b);
00139 if (false === $transparentColor) {
00140 throw new Exception('Failed to allocate transparent color for image.');
00141 }
00142 if (!imagefill($imageResourceTo, 0, 0, $transparentColor)) {
00143 throw new Exception('Failed to fill image with transparency.');
00144 }
00145 imagecolortransparent($imageResourceTo, $transparentColor);
00146 return $transparentColor;
00147 }
00148 }
00149 catch (Exception $e) {
00150
00151 }
00152 }
00153 list($r, $g, $b) = $this->_backgroundColor;
00154 $color = imagecolorallocate($imageResourceTo, $r, $g, $b);
00155 if (!imagefill($imageResourceTo, 0, 0, $color)) {
00156 throw new Exception("Failed to fill image background with color {$r} {$g} {$b}.");
00157 }
00158 return $color;
00159 }
00160
00161 private function _getTransparency($imageResource, $fileType, &$isAlpha = false, &$isTrueColor = false)
00162 {
00163 $isAlpha = false;
00164 $isTrueColor = false;
00165
00166 if ((IMAGETYPE_GIF === $fileType) || (IMAGETYPE_PNG === $fileType)) {
00167
00168 $transparentIndex = imagecolortransparent($imageResource);
00169 if ($transparentIndex >= 0) {
00170 return $transparentIndex;
00171 }
00172
00173 elseif (IMAGETYPE_PNG === $fileType) {
00174 $isAlpha = true;
00175 $isTrueColor = true;
00176 return $transparentIndex;
00177 }
00178 }
00179 if (IMAGETYPE_JPEG === $fileType) {
00180 $isTrueColor = true;
00181 }
00182 return false;
00183 }
00184
00185
00186
00187
00188
00189
00190
00191 public function resize($frameWidth = null, $frameHeight = null)
00192 {
00193 if (empty($frameWidth) && empty($frameHeight)) {
00194 throw new Exception('Invalid image dimensions.');
00195 }
00196
00197
00198 if (!$this->_keepFrame) {
00199 if (null === $frameWidth) {
00200 $frameWidth = round($frameHeight * ($this->_imageSrcWidth / $this->_imageSrcHeight));
00201 }
00202 elseif (null === $frameHeight) {
00203 $frameHeight = round($frameWidth * ($this->_imageSrcHeight / $this->_imageSrcWidth));
00204 }
00205 }
00206 else {
00207 if (null === $frameWidth) {
00208 $frameWidth = $frameHeight;
00209 }
00210 elseif (null === $frameHeight) {
00211 $frameHeight = $frameWidth;
00212 }
00213 }
00214
00215
00216 $srcX = 0;
00217 $srcY = 0;
00218 $dstX = 0;
00219 $dstY = 0;
00220 $dstWidth = $frameWidth;
00221 $dstHeight = $frameHeight;
00222 if ($this->_keepAspectRatio) {
00223
00224 if ($this->_constrainOnly) {
00225 if (($frameWidth >= $this->_imageSrcWidth) && ($frameHeight >= $this->_imageSrcHeight)) {
00226 $dstWidth = $this->_imageSrcWidth;
00227 $dstHeight = $this->_imageSrcHeight;
00228 }
00229 }
00230
00231 if ($this->_imageSrcWidth / $this->_imageSrcHeight >= $frameWidth / $frameHeight) {
00232 $dstHeight = round(($dstWidth / $this->_imageSrcWidth) * $this->_imageSrcHeight);
00233 } else {
00234 $dstWidth = round(($dstHeight / $this->_imageSrcHeight) * $this->_imageSrcWidth);
00235 }
00236 }
00237
00238 $dstY = round(($frameHeight - $dstHeight) / 2);
00239 $dstX = round(($frameWidth - $dstWidth) / 2);
00240
00241
00242 if (!$this->_keepFrame) {
00243 $frameWidth = $dstWidth;
00244 $frameHeight = $dstHeight;
00245 $dstY = 0;
00246 $dstX = 0;
00247 }
00248
00249
00250 $isAlpha = false;
00251 $isTrueColor = false;
00252 $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor);
00253 if ($isTrueColor) {
00254 $newImage = imagecreatetruecolor($frameWidth, $frameHeight);
00255 }
00256 else {
00257 $newImage = imagecreate($frameWidth, $frameHeight);
00258 }
00259
00260
00261 $this->_fillBackgroundColor($newImage);
00262
00263
00264 imagecopyresampled($newImage, $this->_imageHandler, $dstX, $dstY, $srcX, $srcY, $dstWidth, $dstHeight, $this->_imageSrcWidth, $this->_imageSrcHeight);
00265 $this->_imageHandler = $newImage;
00266 $this->refreshImageDimensions();
00267 }
00268
00269 public function rotate($angle)
00270 {
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 $this->_imageHandler = imagerotate($this->_imageHandler, $angle, $this->imageBackgroundColor);
00284 $this->refreshImageDimensions();
00285 }
00286
00287 public function watermark($watermarkImage, $positionX=0, $positionY=0, $watermarkImageOpacity=30, $repeat=false)
00288 {
00289 list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType, ) = getimagesize($watermarkImage);
00290 $this->_getFileAttributes();
00291 $watermark = call_user_func($this->_getCallback('create', $watermarkFileType, 'Unsupported watermark image format.'), $watermarkImage);
00292
00293 $merged = false;
00294
00295 if( $this->getWatermarkWidth() && $this->getWatermarkHeigth() && ($this->getWatermarkPosition() != self::POSITION_STRETCH) ) {
00296 $newWatermark = imagecreatetruecolor($this->getWatermarkWidth(), $this->getWatermarkHeigth());
00297 imagealphablending($newWatermark, false);
00298 $col = imagecolorallocate($newWatermark, 255, 255, 255);
00299 imagecolortransparent($newWatermark, $col);
00300 imagefilledrectangle($newWatermark, 0, 0, $this->getWatermarkWidth(), $this->getWatermarkHeigth(), $col);
00301 imagealphablending($newWatermark, true);
00302
00303 imagecopyresampled($newWatermark, $watermark, 0, 0, 0, 0, $this->getWatermarkWidth(), $this->getWatermarkHeigth(), imagesx($watermark), imagesy($watermark));
00304 $watermark = $newWatermark;
00305 }
00306
00307 if( $this->getWatermarkPosition() == self::POSITION_TILE ) {
00308 $repeat = true;
00309 } elseif( $this->getWatermarkPosition() == self::POSITION_STRETCH ) {
00310 $newWatermark = imagecreatetruecolor($this->_imageSrcWidth, $this->_imageSrcHeight);
00311 imagealphablending($newWatermark, false);
00312 $col = imagecolorallocate($newWatermark, 255, 255, 255);
00313 imagecolortransparent($newWatermark, $col);
00314 imagefilledrectangle($newWatermark, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight, $col);
00315 imagealphablending($newWatermark, true);
00316 imagecopyresampled($newWatermark, $watermark, 0, 0, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight, imagesx($watermark), imagesy($watermark));
00317 $watermark = $newWatermark;
00318 } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_RIGHT ) {
00319 $positionX = ($this->_imageSrcWidth - imagesx($watermark));
00320 imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
00321 $merged = true;
00322 } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_LEFT ) {
00323 imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
00324 $merged = true;
00325 } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT ) {
00326 $positionX = ($this->_imageSrcWidth - imagesx($watermark));
00327 $positionY = ($this->_imageSrcHeight - imagesy($watermark));
00328 imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
00329 $merged = true;
00330 } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT ) {
00331 $positionY = ($this->_imageSrcHeight - imagesy($watermark));
00332 imagecopy($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark));
00333 $merged = true;
00334 }
00335
00336 if( $repeat === false && $merged === false ) {
00337 imagecopymerge($this->_imageHandler, $watermark, $positionX, $positionY, 0, 0, imagesx($watermark), imagesy($watermark), $watermarkImageOpacity);
00338 } else {
00339 $offsetX = $positionX;
00340 $offsetY = $positionY;
00341 while( $offsetY <= ($this->_imageSrcHeight+imagesy($watermark)) ) {
00342 while( $offsetX <= ($this->_imageSrcWidth+imagesx($watermark)) ) {
00343 imagecopy($this->_imageHandler, $watermark, $offsetX, $offsetY, 0, 0, imagesx($watermark), imagesy($watermark));
00344 $offsetX += imagesx($watermark);
00345 }
00346 $offsetX = $positionX;
00347 $offsetY += imagesy($watermark);
00348 }
00349 }
00350 imagedestroy($watermark);
00351 $this->refreshImageDimensions();
00352 }
00353
00354 public function crop($top=0, $bottom=0, $right=0, $left=0)
00355 {
00356 if( $left == 0 && $top == 0 && $right == 0 && $bottom == 0 ) {
00357 return;
00358 }
00359
00360 $newWidth = $this->_imageSrcWidth - $left - $right;
00361 $newHeight = $this->_imageSrcHeight - $top - $bottom;
00362
00363 $canvas = imagecreatetruecolor($newWidth, $newHeight);
00364
00365 if ($this->_fileType == IMAGETYPE_PNG) {
00366 $this->_saveAlpha($canvas);
00367 }
00368
00369 imagecopyresampled($canvas, $this->_imageHandler, $top, $bottom, $right, $left, $this->_imageSrcWidth, $this->_imageSrcHeight, $newWidth, $newHeight);
00370
00371 $this->_imageHandler = $canvas;
00372 $this->refreshImageDimensions();
00373 }
00374
00375 public function checkDependencies()
00376 {
00377 foreach( $this->_requiredExtensions as $value ) {
00378 if( !extension_loaded($value) ) {
00379 throw new Exception("Required PHP extension '{$value}' was not loaded.");
00380 }
00381 }
00382 }
00383
00384 private function refreshImageDimensions()
00385 {
00386 $this->_imageSrcWidth = imagesx($this->_imageHandler);
00387 $this->_imageSrcHeight = imagesy($this->_imageHandler);
00388 }
00389
00390 function __destruct()
00391 {
00392 @imagedestroy($this->_imageHandler);
00393 }
00394
00395
00396
00397
00398 private function _saveAlpha($imageHandler)
00399 {
00400 $background = imagecolorallocate($imageHandler, 0, 0, 0);
00401 ImageColorTransparent($imageHandler, $background);
00402 imagealphablending($imageHandler, false);
00403 imagesavealpha($imageHandler, true);
00404 }
00405 }