Last active
December 18, 2015 05:49
-
-
Save gsomoza/5735302 to your computer and use it in GitHub Desktop.
ImageMagick Support for OnePica_ImageCdn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Overrides for OnePica_ImageCdn | |
* | |
* NOTICE OF LICENSE | |
* | |
* This source file is subject to the Open Software License (OSL 3.0), a | |
* copy of which is available through the world-wide-web at this URL: | |
* http://opensource.org/licenses/osl-3.0.php | |
* | |
* @category GabrielSomoza | |
* @package ImageCdn | |
* @author Gabriel Somoza <[email protected]> | |
* @copyright Copyright (c) 2013 Gabriel Somoza. | |
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
*/ | |
/** | |
* ImageCDN extension to use custom ImageMagick lib | |
* @category GabrielSomoza | |
* @package ImageCdn | |
*/ | |
class GabrielSomoza_ImageCdn_Model_Varien_Image extends Varien_Image | |
{ | |
/** | |
* Defaults $adapter to this module's ImageMagick adapter. | |
* | |
* @param null|Varien_Image_Adapter_Abstract $adapter | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
protected function _getAdapter($adapter=null) | |
{ | |
if( !isset($this->_adapter) ) { | |
$this->_adapter = Mage::getModel('gabrielsomoza_imagecdn/varien_image_adapter_imagemagick'); | |
} | |
return $this->_adapter; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* NOTICE OF LICENSE | |
* | |
* This source file is subject to the Open Software License (OSL 3.0), a | |
* copy of which is available through the world-wide-web at this URL: | |
* http://opensource.org/licenses/osl-3.0.php | |
* | |
* @category GabrielSomoza | |
* @package ImageCdn | |
* @author Gabriel Somoza <[email protected]> | |
* @copyright Copyright (c) 2013 GabrielSomoza. | |
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
*/ | |
/** | |
* ImageMagick Adapter implementation | |
* @category GabrielSomoza | |
* @package ImageCdn | |
*/ | |
class GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick extends GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick_Abstract | |
{ | |
/** | |
* The blur factor where > 1 is blurry, < 1 is sharp | |
*/ | |
const BLUR_FACTOR = 0.7; | |
/** | |
* Error messages | |
*/ | |
const ERROR_WATERMARK_IMAGE_ABSENT = 'Watermark Image absent.'; | |
const ERROR_WRONG_IMAGE = 'Image is not readable or file name is empty.'; | |
/** | |
* Options Container | |
* | |
* @var array | |
*/ | |
protected $_options = array( | |
'resolution' => array( | |
'x' => 72, | |
'y' => 72 | |
), | |
'small_image' => array( | |
'width' => 300, | |
'height' => 300 | |
), | |
'sharpen' => array( | |
'radius' => 4, | |
'deviation' => 1 | |
) | |
); | |
/** | |
* Set/get background color. Check Imagick::COLOR_* constants | |
* | |
* @param int|string|array $color | |
* @return int | |
*/ | |
public function backgroundColor($color = null) | |
{ | |
if ($color) { | |
if (is_array($color)) { | |
$color = "rgb(" . join(',', $color) . ")"; | |
} | |
$pixel = new ImagickPixel; | |
if (is_numeric($color)) { | |
$pixel->setColorValue($color, 1); | |
} else { | |
$pixel->setColor($color); | |
} | |
if ($this->_imageHandler) { | |
$this->_imageHandler->setImageBackgroundColor($color); | |
} | |
} else { | |
$pixel = $this->_imageHandler->getImageBackgroundColor(); | |
} | |
$this->imageBackgroundColor = $pixel->getColorAsString(); | |
return $this->imageBackgroundColor; | |
} | |
/** | |
* Open image for processing | |
* | |
* @throws Exception | |
* @param string $filename | |
*/ | |
public function open($filename) | |
{ | |
$this->_fileName = $filename; | |
$this->_checkCanProcess(); | |
$this->_getFileAttributes(); | |
try { | |
$this->_imageHandler = new Imagick($this->_fileName); | |
} catch (ImagickException $e) { | |
throw new Exception('Unsupported image format.', $e->getCode(), $e); | |
} | |
$this->backgroundColor(); | |
$this->getMimeType(); | |
} | |
/** | |
* Save image to specific path and hijacks the normal save method to add ImageCDN hooks if necessary. | |
* If some folders of path does not exist they will be created. | |
* | |
* @param string $destination | |
* @param string $newName | |
* @throws Exception | |
*/ | |
public function save($destination = null, $newName = null) | |
{ | |
/** @var OnePica_ImageCdn_Model_Adapter_Abstract $cds */ | |
$cds = Mage::helper('imagecdn')->factory(); | |
$compression = Mage::getStoreConfig('imagecdn/general/compression'); | |
//Compress images? | |
$quality = round((10-$compression)*10); //convert to percentage | |
$this->quality($quality); | |
if($cds->useCdn()) { | |
$temp = tempnam(sys_get_temp_dir(), 'cds'); | |
$this->_save($temp); | |
$filename = ( !isset($destination) ) ? $this->_fileName : $destination; | |
if( isset($destination) && isset($newName) ) { | |
$filename = $destination . "/" . $filename; | |
} elseif( isset($destination) && !isset($newName) ) { | |
$info = pathinfo($destination); | |
$filename = $destination; | |
$destination = $info['dirname']; | |
} elseif( !isset($destination) && isset($newName) ) { | |
$filename = $this->_fileSrcPath . "/" . $newName; | |
} else { | |
$filename = $this->_fileSrcPath . $this->_fileSrcName; | |
} | |
if($cds->save($filename, $temp)) { | |
@unlink($temp); | |
} else { | |
if(!is_writable($destination)) { | |
try { | |
$io = new Varien_Io_File(); | |
$io->mkdir($destination); | |
} catch (Exception $e) { | |
throw new Exception("Unable to write file into directory '{$destination}'. Access forbidden."); | |
} | |
} | |
@rename($temp, $filename); | |
@chmod($filename, 0644); | |
} | |
} else { | |
$this->_save($destination, $newName); | |
} | |
} | |
/** | |
* Apply options to image. Will be usable later when create an option container | |
* | |
* @return Varien_Image_Adapter_ImageMagick | |
*/ | |
protected function _applyOptions() | |
{ | |
$this->_imageHandler->setImageCompressionQuality($this->quality()); | |
$this->_imageHandler->setImageCompression(Imagick::COMPRESSION_JPEG); | |
$this->_imageHandler->setImageUnits(Imagick::RESOLUTION_PIXELSPERINCH); | |
$this->_imageHandler->setImageResolution( | |
$this->_options['resolution']['x'], | |
$this->_options['resolution']['y'] | |
); | |
if (method_exists($this->_imageHandler, 'optimizeImageLayers')) { | |
$this->_imageHandler->optimizeImageLayers(); | |
} | |
return $this; | |
} | |
/** | |
* @see Varien_Image_Adapter_Abstract::getImage | |
* @return string | |
*/ | |
public function getImage() | |
{ | |
$this->_applyOptions(); | |
return (string)$this->_imageHandler; | |
} | |
/** | |
* Change the image size | |
* | |
* @param int $frameWidth | |
* @param int $frameHeight | |
* @throws Exception | |
*/ | |
public function resize($frameWidth = null, $frameHeight = null) | |
{ | |
$this->_checkCanProcess(); | |
$dims = $this->_adaptResizeValues($frameWidth, $frameHeight); | |
$newImage = new Imagick(); | |
$newImage->newImage( | |
$dims['frame']['width'], | |
$dims['frame']['height'], | |
$this->_imageHandler->getImageBackgroundColor() | |
); | |
$this->_imageHandler->resizeImage( | |
$dims['dst']['width'], | |
$dims['dst']['height'], | |
Imagick::FILTER_CUBIC, | |
self::BLUR_FACTOR | |
); | |
if ($this->_imageHandler->getImageWidth() < $this->_options['small_image']['width'] | |
|| $this->_imageHandler->getImageHeight() < $this->_options['small_image']['height'] | |
) { | |
$this->_imageHandler->sharpenImage( | |
$this->_options['sharpen']['radius'], | |
$this->_options['sharpen']['deviation'] | |
); | |
} | |
$newImage->compositeImage( | |
$this->_imageHandler, | |
Imagick::COMPOSITE_OVER, | |
$dims['dst']['x'], | |
$dims['dst']['y'] | |
); | |
$newImage->setImageFormat($this->_imageHandler->getImageFormat()); | |
$this->_imageHandler->clear(); | |
$this->_imageHandler->destroy(); | |
$this->_imageHandler = $newImage; | |
$this->refreshImageDimensions(); | |
} | |
/** | |
* Rotate image on specific angle | |
* | |
* @param int $angle | |
* @throws Exception | |
*/ | |
public function rotate($angle) | |
{ | |
$this->_checkCanProcess(); | |
// compatibility with GD2 adapter | |
$angle = 360 - $angle; | |
$pixel = new ImagickPixel; | |
$pixel->setColor("rgb(" . $this->imageBackgroundColor . ")"); | |
$this->_imageHandler->rotateImage($pixel, $angle); | |
$this->refreshImageDimensions(); | |
} | |
/** | |
* Crop image | |
* | |
* @param int $top | |
* @param int $left | |
* @param int $right | |
* @param int $bottom | |
* @return bool | |
*/ | |
public function crop($top = 0, $left = 0, $right = 0, $bottom = 0) | |
{ | |
if ($left == 0 && $top == 0 && $right == 0 && $bottom == 0 | |
|| !$this->_canProcess() | |
) { | |
return false; | |
} | |
$newWidth = $this->_imageSrcWidth - $left - $right; | |
$newHeight = $this->_imageSrcHeight - $top - $bottom; | |
$this->_imageHandler->cropImage($newWidth, $newHeight, $left, $top); | |
$this->refreshImageDimensions(); | |
return true; | |
} | |
/** | |
* Add watermark to image | |
* | |
* @param $imagePath | |
* @param int $positionX | |
* @param int $positionY | |
* @param int $opacity | |
* @param bool $tile | |
* @throws Exception | |
*/ | |
public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = 30, $tile = false) | |
{ | |
if (empty($imagePath) || !file_exists($imagePath)) { | |
throw new Exception(self::ERROR_WATERMARK_IMAGE_ABSENT); | |
} | |
$this->_checkCanProcess(); | |
$opacity = $this->getWatermarkImageOpacity() ? $this->getWatermarkImageOpacity() : $opacity; | |
$opacity = (float)number_format($opacity / 100, 1); | |
$watermark = new Imagick($imagePath); | |
if ($this->getWatermarkWidth() && | |
$this->getWatermarkHeight() && | |
$this->getWatermarkPosition() != self::POSITION_STRETCH | |
) { | |
$watermark->resizeImage( | |
$this->getWatermarkWidth(), | |
$this->getWatermarkHeight(), | |
Imagick::FILTER_CUBIC, | |
self::BLUR_FACTOR | |
); | |
} | |
if (method_exists($watermark, 'setImageOpacity')) { | |
// available from imagick 6.3.1 | |
$watermark->setImageOpacity($opacity); | |
} else { | |
// go to each pixel and make it transparent | |
$watermark->paintTransparentImage($watermark->getImagePixelColor(0, 0), 1, 65530); | |
$watermark->evaluateImage(Imagick::EVALUATE_SUBTRACT, 1 - $opacity, Imagick::CHANNEL_ALPHA); | |
} | |
switch ($this->getWatermarkPosition()) { | |
case self::POSITION_STRETCH: | |
$watermark->sampleImage($this->_imageSrcWidth, $this->_imageSrcHeight); | |
break; | |
case self::POSITION_CENTER: | |
$positionX = ($this->_imageSrcWidth - $watermark->getImageWidth())/2; | |
$positionY = ($this->_imageSrcHeight - $watermark->getImageHeight())/2; | |
break; | |
case self::POSITION_TOP_RIGHT: | |
$positionX = $this->_imageSrcWidth - $watermark->getImageWidth(); | |
break; | |
case self::POSITION_BOTTOM_RIGHT: | |
$positionX = $this->_imageSrcWidth - $watermark->getImageWidth(); | |
$positionY = $this->_imageSrcHeight - $watermark->getImageHeight(); | |
break; | |
case self::POSITION_BOTTOM_LEFT: | |
$positionY = $this->_imageSrcHeight - $watermark->getImageHeight(); | |
break; | |
case self::POSITION_TILE: | |
$positionX = 0; | |
$positionY = 0; | |
$tile = true; | |
break; | |
} | |
try { | |
if ($tile) { | |
$offsetX = $positionX; | |
$offsetY = $positionY; | |
while($offsetY <= ($this->_imageSrcHeight + $watermark->getImageHeight())) { | |
while($offsetX <= ($this->_imageSrcWidth + $watermark->getImageWidth())) { | |
$this->_imageHandler->compositeImage( | |
$watermark, | |
Imagick::COMPOSITE_OVER, | |
$offsetX, | |
$offsetY | |
); | |
$offsetX += $watermark->getImageWidth(); | |
} | |
$offsetX = $positionX; | |
$offsetY += $watermark->getImageHeight(); | |
} | |
} else { | |
$this->_imageHandler->compositeImage( | |
$watermark, | |
Imagick::COMPOSITE_OVER, | |
$positionX, | |
$positionY | |
); | |
} | |
} catch (ImagickException $e) { | |
throw new Exception('Unable to create watermark.', $e->getCode(), $e); | |
} | |
// merge layers | |
$this->_imageHandler->flattenImages(); | |
$watermark->clear(); | |
$watermark->destroy(); | |
} | |
/** | |
* Checks required dependecies | |
* | |
* @throws Exception if some of dependecies are missing | |
*/ | |
public function checkDependencies() | |
{ | |
if (!class_exists('Imagick', false)) { | |
throw new Exception("Required PHP extension 'Imagick' was not loaded."); | |
} | |
} | |
/** | |
* Reassign image dimensions | |
*/ | |
private function refreshImageDimensions() | |
{ | |
$this->_imageSrcWidth = $this->_imageHandler->getImageWidth(); | |
$this->_imageSrcHeight = $this->_imageHandler->getImageHeight(); | |
$this->_imageHandler->setImagePage($this->_imageSrcWidth, $this->_imageSrcHeight, 0, 0); | |
} | |
/** | |
* Standard destructor. Destroy stored information about image | |
* | |
*/ | |
public function __destruct() | |
{ | |
$this->destroy(); | |
} | |
/** | |
* Destroy stored information about image | |
* | |
* @return Varien_Image_Adapter_ImageMagick | |
*/ | |
public function destroy() | |
{ | |
if (null !== $this->_imageHandler && $this->_imageHandler instanceof Imagick) { | |
$this->_imageHandler->clear(); | |
$this->_imageHandler->destroy(); | |
$this->_imageHandler = null; | |
} | |
return $this; | |
} | |
/** | |
* Returns rgb array of the specified pixel | |
* | |
* @param int $x | |
* @param int $y | |
* @return array | |
*/ | |
public function getColorAt($x, $y) | |
{ | |
$pixel = $this->_imageHandler->getImagePixelColor($x, $y); | |
return explode(',', $pixel->getColorAsString()); | |
} | |
/** | |
* Check whether the adapter can work with the image | |
* | |
* @throws Exception | |
* @return bool | |
*/ | |
protected function _checkCanProcess() | |
{ | |
if (!$this->_canProcess()) { | |
throw new Exception(self::ERROR_WRONG_IMAGE); | |
} | |
return true; | |
} | |
/** | |
* @param $destination | |
* @param $newName | |
*/ | |
protected function _save($destination=null, $newName=null) | |
{ | |
$fileName = $this->_prepareDestination($destination, $newName); | |
$this->_applyOptions(); | |
$this->_imageHandler->stripImage(); | |
$this->_imageHandler->writeImage($fileName); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Overrides for OnePica_ImageCdn | |
* | |
* NOTICE OF LICENSE | |
* | |
* This source file is subject to the Open Software License (OSL 3.0), a | |
* copy of which is available through the world-wide-web at this URL: | |
* http://opensource.org/licenses/osl-3.0.php | |
* | |
* @category GabrielSomoza | |
* @package ImageCdn | |
* @author Gabriel Somoza <[email protected]> | |
* @copyright Copyright (c) 2013 GabrielSomoza, Inc. | |
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) | |
*/ | |
/** | |
* Abastract adapter for ImageMagick | |
* @category GabrielSomoza | |
* @package ImageCdn | |
*/ | |
abstract class GabrielSomoza_ImageCdn_Model_Varien_Image_Adapter_Imagemagick_Abstract | |
{ | |
/** | |
* Background color | |
* @var mixed | |
*/ | |
public $imageBackgroundColor = 0; | |
/** | |
* Position constants | |
*/ | |
const POSITION_TOP_LEFT = 'top-left'; | |
const POSITION_TOP_RIGHT = 'top-right'; | |
const POSITION_BOTTOM_LEFT = 'bottom-left'; | |
const POSITION_BOTTOM_RIGHT = 'bottom-right'; | |
const POSITION_STRETCH = 'stretch'; | |
const POSITION_TILE = 'tile'; | |
const POSITION_CENTER = 'center'; | |
protected $_fileType; | |
protected $_fileName ; | |
protected $_fileMimeType; | |
protected $_fileSrcName; | |
protected $_fileSrcPath; | |
protected $_imageHandler; | |
protected $_imageSrcWidth; | |
protected $_imageSrcHeight; | |
protected $_requiredExtensions; | |
protected $_watermarkPosition; | |
protected $_watermarkWidth; | |
protected $_watermarkHeigth; | |
protected $_watermarkImageOpacity; | |
protected $_quality; | |
protected $_keepAspectRatio; | |
protected $_keepFrame; | |
protected $_keepTransparency; | |
protected $_backgroundColor; | |
protected $_constrainOnly; | |
/** | |
* IO model to work with files | |
* @var Varien_Io_File | |
*/ | |
protected $_ioFile; | |
abstract public function open($fileName); | |
abstract public function save($destination = null, $newName = null); | |
/** | |
* Render image and return its binary contents | |
* | |
* @return string | |
*/ | |
abstract public function getImage(); | |
abstract public function resize($width=null, $height=null); | |
abstract public function rotate($angle); | |
abstract public function crop($top = 0, $left = 0, $right = 0, $bottom = 0); | |
abstract public function watermark($imagePath, $positionX = 0, $positionY = 0, $opacity = 30, $tile = false); | |
abstract public function checkDependencies(); | |
/** | |
* Initialize default values | |
* | |
* @param array $data | |
*/ | |
public function __construct(array $data = array()) | |
{ | |
$this->_ioFile = isset($data['io']) ? $data['io'] : new Varien_Io_File(); | |
} | |
/** | |
* Assign image width, height, fileType and fileMimeType to object properties | |
* using getimagesize function | |
* | |
* @return int|null | |
*/ | |
public function getMimeType() | |
{ | |
if( $this->_fileType ) { | |
return $this->_fileType; | |
} else { | |
list($this->_imageSrcWidth, $this->_imageSrcHeight, $this->_fileType, ) = getimagesize($this->_fileName); | |
$this->_fileMimeType = image_type_to_mime_type($this->_fileType); | |
return $this->_fileMimeType; | |
} | |
} | |
/** | |
* Retrieve Original Image Width | |
* | |
* @return int|null | |
*/ | |
public function getOriginalWidth() | |
{ | |
$this->getMimeType(); | |
return $this->_imageSrcWidth; | |
} | |
/** | |
* Retrieve Original Image Height | |
* | |
* @return int|null | |
*/ | |
public function getOriginalHeight() | |
{ | |
$this->getMimeType(); | |
return $this->_imageSrcHeight; | |
} | |
/** | |
* Set watermark position | |
* | |
* @param $position | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
public function setWatermarkPosition($position) | |
{ | |
$this->_watermarkPosition = $position; | |
return $this; | |
} | |
/** | |
* Get watermark position | |
* | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
public function getWatermarkPosition() | |
{ | |
return $this->_watermarkPosition; | |
} | |
/** | |
* Set watermark opacity | |
* | |
* @param $imageOpacity | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
public function setWatermarkImageOpacity($imageOpacity) | |
{ | |
$this->_watermarkImageOpacity = $imageOpacity; | |
return $this; | |
} | |
/** | |
* Get watermark opacity | |
* | |
* @return int | |
*/ | |
public function getWatermarkImageOpacity() | |
{ | |
return $this->_watermarkImageOpacity; | |
} | |
/** | |
* Set watermark width | |
* | |
* @param $width | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
public function setWatermarkWidth($width) | |
{ | |
$this->_watermarkWidth = $width; | |
return $this; | |
} | |
/** | |
* Get watermark width | |
* | |
* @return int | |
*/ | |
public function getWatermarkWidth() | |
{ | |
return $this->_watermarkWidth; | |
} | |
/** | |
* Set watermark height | |
* | |
* @param $heigth | |
* @return Varien_Image_Adapter_Abstract | |
*/ | |
public function setWatermarkHeight($heigth) | |
{ | |
$this->_watermarkHeigth = $heigth; | |
return $this; | |
} | |
/** | |
* Return watermark height | |
* | |
* @return int | |
*/ | |
public function getWatermarkHeight() | |
{ | |
return $this->_watermarkHeigth; | |
} | |
/** | |
* Get/set keepAspectRatio | |
* | |
* @param bool $value | |
* @return bool|Varien_Image_Adapter_Abstract | |
*/ | |
public function keepAspectRatio($value = null) | |
{ | |
if (null !== $value) { | |
$this->_keepAspectRatio = (bool)$value; | |
} | |
return $this->_keepAspectRatio; | |
} | |
/** | |
* Get/set keepFrame | |
* | |
* @param bool $value | |
* @return bool | |
*/ | |
public function keepFrame($value = null) | |
{ | |
if (null !== $value) { | |
$this->_keepFrame = (bool)$value; | |
} | |
return $this->_keepFrame; | |
} | |
/** | |
* Get/set keepTransparency | |
* | |
* @param bool $value | |
* @return bool | |
*/ | |
public function keepTransparency($value = null) | |
{ | |
if (null !== $value) { | |
$this->_keepTransparency = (bool)$value; | |
} | |
return $this->_keepTransparency; | |
} | |
/** | |
* Get/set constrainOnly | |
* | |
* @param bool $value | |
* @return bool | |
*/ | |
public function constrainOnly($value = null) | |
{ | |
if (null !== $value) { | |
$this->_constrainOnly = (bool)$value; | |
} | |
return $this->_constrainOnly; | |
} | |
/** | |
* Get/set quality, values in percentage from 0 to 100 | |
* | |
* @param int $value | |
* @return int | |
*/ | |
public function quality($value = null) | |
{ | |
if (null !== $value) { | |
$this->_quality = (int)$value; | |
} | |
return $this->_quality; | |
} | |
/** | |
* Get/set keepBackgroundColor | |
* | |
* @param array $value | |
* @return array | |
*/ | |
public function backgroundColor($value = null) | |
{ | |
if (null !== $value) { | |
if ((!is_array($value)) || (3 !== count($value))) { | |
return; | |
} | |
foreach ($value as $color) { | |
if ((!is_integer($color)) || ($color < 0) || ($color > 255)) { | |
return; | |
} | |
} | |
} | |
$this->_backgroundColor = $value; | |
return $this->_backgroundColor; | |
} | |
/** | |
* Assign file dirname and basename to object properties | |
* | |
*/ | |
protected function _getFileAttributes() | |
{ | |
$pathinfo = pathinfo($this->_fileName); | |
$this->_fileSrcPath = $pathinfo['dirname']; | |
$this->_fileSrcName = $pathinfo['basename']; | |
} | |
/** | |
* Adapt resize values based on image configuration | |
* | |
* @throws Exception | |
* @param int $frameWidth | |
* @param int $frameHeight | |
* @return array | |
*/ | |
protected function _adaptResizeValues($frameWidth, $frameHeight) | |
{ | |
$this->_checkDimensions($frameWidth, $frameHeight); | |
// calculate lacking dimension | |
if (!$this->_keepFrame && $this->_checkSrcDimensions()) { | |
if (null === $frameWidth) { | |
$frameWidth = round($frameHeight * ($this->_imageSrcWidth / $this->_imageSrcHeight)); | |
} elseif (null === $frameHeight) { | |
$frameHeight = round($frameWidth * ($this->_imageSrcHeight / $this->_imageSrcWidth)); | |
} | |
} else { | |
if (null === $frameWidth) { | |
$frameWidth = $frameHeight; | |
} elseif (null === $frameHeight) { | |
$frameHeight = $frameWidth; | |
} | |
} | |
// define coordinates of image inside new frame | |
$srcX = 0; | |
$srcY = 0; | |
list($dstWidth, $dstHeight) = $this->_checkAspectRatio($frameWidth, $frameHeight); | |
// define position in center | |
// TODO: add positions option | |
$dstY = round(($frameHeight - $dstHeight) / 2); | |
$dstX = round(($frameWidth - $dstWidth) / 2); | |
// get rid of frame (fallback to zero position coordinates) | |
if (!$this->_keepFrame) { | |
$frameWidth = $dstWidth; | |
$frameHeight = $dstHeight; | |
$dstY = 0; | |
$dstX = 0; | |
} | |
return array( | |
'src' => array( | |
'x' => $srcX, | |
'y' => $srcY | |
), | |
'dst' => array( | |
'x' => $dstX, | |
'y' => $dstY, | |
'width' => $dstWidth, | |
'height' => $dstHeight | |
), | |
'frame' => array( // size for new image | |
'width' => $frameWidth, | |
'height' => $frameHeight | |
) | |
); | |
} | |
/** | |
* Check aspect ratio | |
* | |
* @param int $frameWidth | |
* @param int $frameHeight | |
* @return array | |
*/ | |
protected function _checkAspectRatio($frameWidth, $frameHeight) | |
{ | |
$dstWidth = $frameWidth; | |
$dstHeight = $frameHeight; | |
if ($this->_keepAspectRatio && $this->_checkSrcDimensions()) { | |
// do not make picture bigger, than it is, if required | |
if ($this->_constrainOnly) { | |
if (($frameWidth >= $this->_imageSrcWidth) && ($frameHeight >= $this->_imageSrcHeight)) { | |
$dstWidth = $this->_imageSrcWidth; | |
$dstHeight = $this->_imageSrcHeight; | |
} | |
} | |
// keep aspect ratio | |
if ($this->_imageSrcWidth / $this->_imageSrcHeight >= $frameWidth / $frameHeight) { | |
$dstHeight = round(($dstWidth / $this->_imageSrcWidth) * $this->_imageSrcHeight); | |
} else { | |
$dstWidth = round(($dstHeight / $this->_imageSrcHeight) * $this->_imageSrcWidth); | |
} | |
} | |
return array($dstWidth, $dstHeight); | |
} | |
/** | |
* Check Frame dimensions and throw exception if they are not valid | |
* | |
* @param int $frameWidth | |
* @param int $frameHeight | |
* @throws Exception | |
*/ | |
protected function _checkDimensions($frameWidth, $frameHeight) | |
{ | |
if ($frameWidth !== null && $frameWidth <= 0 | |
|| $frameHeight !== null && $frameHeight <= 0 | |
|| empty($frameWidth) && empty($frameHeight) | |
) { | |
throw new Exception('Invalid image dimensions.'); | |
} | |
} | |
/** | |
* Return false if source width or height is empty | |
* | |
* @return bool | |
*/ | |
protected function _checkSrcDimensions() | |
{ | |
return !empty($this->_imageSrcWidth) && !empty($this->_imageSrcHeight); | |
} | |
/** | |
* Return information about image using getimagesize function | |
* | |
* @param string $filePath | |
* @return array | |
*/ | |
protected function _getImageOptions($filePath) | |
{ | |
return getimagesize($filePath); | |
} | |
/** | |
* Return supported image formats | |
* | |
* @return array | |
*/ | |
public function getSupportedFormats() | |
{ | |
return array('gif', 'jpeg', 'jpg', 'png'); | |
} | |
/** | |
* Create destination folder if not exists and return full file path | |
* | |
* @throws Exception | |
* @param string $destination | |
* @param string $newName | |
* @return string | |
*/ | |
protected function _prepareDestination($destination = null, $newName = null) | |
{ | |
if (empty($destination)) { | |
$destination = $this->_fileSrcPath; | |
} else { | |
if (empty($newName)) { | |
$info = pathinfo($destination); | |
$newName = $info['basename']; | |
$destination = $info['dirname']; | |
} | |
} | |
if (empty($newName)) { | |
$newFileName = $this->_fileSrcName; | |
} else { | |
$newFileName = $newName; | |
} | |
$fileName = $destination . DIRECTORY_SEPARATOR . $newFileName; | |
if (!is_writable($destination)) { | |
try { | |
$result = $this->_ioFile->mkdir($destination); | |
} catch (Exception $e) { | |
$result = false; | |
} | |
if (!$result) { | |
throw new Exception('Unable to write file into directory ' . $destination . '. Access forbidden.'); | |
} | |
} | |
return $fileName; | |
} | |
/** | |
* Checks is adapter can work with image | |
* | |
* @return bool | |
*/ | |
protected function _canProcess() | |
{ | |
return !empty($this->_fileName); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment