doudu22272099831 2014-08-12 23:54
浏览 81

Magento + Imagemagick比例图像

Implemented Imagemagick instead of GD2 in Magento 1.7.0.2 as suggested here:

http://www.magentocommerce.com/boards/v/viewthread/6158/P135/#t328638

However the new images are not proportional, causing stretching. They were perfect with GD2

Instructions:

In the Gd2.php file, in the save() function comment out

call_user_func_array($this->_getCallback('output'), $functionParameters);

This is the where Magento calls the imagejpeg() function. Yuck.

Now add the following code just below the commented out line.

$source_file = $this->_fileSrcPath.'/'.$this->_fileSrcName;
$image_info = getimagesize($source_file);
$im = new Imagick();
$im->readImage($source_file);

//check to see if image needs to be resized (eg. thumbnails)
if ($image_info[0] != $this->_imageSrcWidth) {
 $im->thumbnailImage($this->_imageSrcWidth, $this->_imageSrcHeight);
}
$im->writeImage($fileName);

Here is the implemented code

        <?php
        /**
         * Magento
         *
         * NOTICE OF LICENSE
         *
         * This source file is subject to the Open Software License (OSL 3.0)
         * that is bundled with this package in the file LICENSE.txt.
         * It is also available through the world-wide-web at this URL:
         * http://opensource.org/licenses/osl-3.0.php
         * If you did not receive a copy of the license and are unable to
         * obtain it through the world-wide-web, please send an email
         * to license@magentocommerce.com so we can send you a copy immediately.
         *
         * DISCLAIMER
         *
         * Do not edit or add to this file if you wish to upgrade Magento to newer
         * versions in the future. If you wish to customize Magento for your
         * needs please refer to http://www.magentocommerce.com for more information.
         *
         * @category   Varien
         * @package    Varien_Image
         * @copyright  Copyright (c) 2008 Irubin Consulting Inc. DBA Varien (http://www.varien.com)
         * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
         */


        class Varien_Image_Adapter_Gd2 extends Varien_Image_Adapter_Abstract
        {
            protected $_requiredExtensions = Array("gd");
            private static $_callbacks = array(
                IMAGETYPE_GIF  => array('output' => 'imagegif',  'create' => 'imagecreatefromgif'),
                IMAGETYPE_JPEG => array('output' => 'imagejpeg', 'create' => 'imagecreatefromjpeg'),
                IMAGETYPE_PNG  => array('output' => 'imagepng',  'create' => 'imagecreatefrompng'),
                IMAGETYPE_XBM  => array('output' => 'imagexbm',  'create' => 'imagecreatefromxbm'),
                IMAGETYPE_WBMP => array('output' => 'imagewbmp', 'create' => 'imagecreatefromxbm'),
            );

            /**
             * Whether image was resized or not
             *
             * @var bool
             */
            protected $_resized = false;

            public function open($filename)
            {
                $this->_fileName = $filename;
                $this->getMimeType();
                $this->_getFileAttributes();
                $this->_imageHandler = call_user_func($this->_getCallback('create'), $this->_fileName);
            }

            public function save($destination=null, $newName=null)
            {
                $fileName = ( !isset($destination) ) ? $this->_fileName : $destination;

                if( isset($destination) && isset($newName) ) {
                    $fileName = $destination . "/" . $newName;
                } 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;
                }

                $destinationDir = ( isset($destination) ) ? $destination : $this->_fileSrcPath;

                if( !is_writable($destinationDir) ) {
                    try {
                        $io = new Varien_Io_File();
                        $io->mkdir($destination);
                    } catch (Exception $e) {
                        throw new Exception("Unable to write file into directory '{$destinationDir}'. Access forbidden.");
                    }
                }

                if (!$this->_resized) {
                    // keep alpha transparency
                    $isAlpha     = false;
                    $isTrueColor = false;
                    $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor);
                    if ($isAlpha) {
                        if ($isTrueColor) {
                            $newImage = imagecreatetruecolor($this->_imageSrcWidth, $this->_imageSrcHeight);
                        } else {
                            $newImage = imagecreate($this->_imageSrcWidth, $this->_imageSrcHeight);
                        }
                        $this->_fillBackgroundColor($newImage);
                        imagecopy(
                            $newImage,
                            $this->_imageHandler,
                            0, 0,
                            0, 0,
                            $this->_imageSrcWidth, $this->_imageSrcHeight
                        );
                        $this->_imageHandler = $newImage;
                    }
                }

                $functionParameters = array();
                $functionParameters[] = $this->_imageHandler;
                $functionParameters[] = $fileName;

                // set quality param for JPG file type
                if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_JPEG)
                {
                    $functionParameters[] = $this->quality();
                }

                // set quality param for PNG file type
                if (!is_null($this->quality()) && $this->_fileType == IMAGETYPE_PNG)
                {
                    $quality = round(($this->quality() / 100) * 10);
                    if ($quality < 1) {
                        $quality = 1;
                    } elseif ($quality > 10) {
                        $quality = 10;
                    }
                    $quality = 10 - $quality;
                    $functionParameters[] = $quality;
                }

                //call_user_func_array($this->_getCallback('output'), $functionParameters);

                $source_file = $this->_fileSrcPath.'/'.$this->_fileSrcName;
                $image_info = getimagesize($source_file);
                $im = new Imagick();
                $im->readImage($source_file);

                //check to see if image needs to be resized (eg. thumbnails)
                if ($image_info[0] != $this->_imageSrcWidth) {
                     $im->thumbnailImage($this->_imageSrcWidth, $this->_imageSrcHeight);
                }
                $im->writeImage($fileName);
            }

            public function display()
            {
                header("Content-type: ".$this->getMimeType());
                call_user_func($this->_getCallback('output'), $this->_imageHandler);
            }

            /**
             * Obtain function name, basing on image type and callback type
             *
             * @param string $callbackType
             * @param int $fileType
             * @return string
             * @throws Exception
             */
            private function _getCallback($callbackType, $fileType = null, $unsupportedText = 'Unsupported image format.')
            {
                if (null === $fileType) {
                    $fileType = $this->_fileType;
                }
                if (empty(self::$_callbacks[$fileType])) {
                    throw new Exception($unsupportedText);
                }
                if (empty(self::$_callbacks[$fileType][$callbackType])) {
                    throw new Exception('Callback not found.');
                }
                return self::$_callbacks[$fileType][$callbackType];
            }

            private function _fillBackgroundColor(&$imageResourceTo)
            {
                // try to keep transparency, if any
                if ($this->_keepTransparency) {
                    $isAlpha = false;
                    $transparentIndex = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
                    try {
                        // fill truecolor png with alpha transparency
                        if ($isAlpha) {

                            if (!imagealphablending($imageResourceTo, false)) {
                                throw new Exception('Failed to set alpha blending for PNG image.');
                            }
                            $transparentAlphaColor = imagecolorallocatealpha($imageResourceTo, 0, 0, 0, 127);
                            if (false === $transparentAlphaColor) {
                                throw new Exception('Failed to allocate alpha transparency for PNG image.');
                            }
                            if (!imagefill($imageResourceTo, 0, 0, $transparentAlphaColor)) {
                                throw new Exception('Failed to fill PNG image with alpha transparency.');
                            }
                            if (!imagesavealpha($imageResourceTo, true)) {
                                throw new Exception('Failed to save alpha transparency into PNG image.');
                            }

                            return $transparentAlphaColor;
                        }
                        // fill image with indexed non-alpha transparency
                        elseif (false !== $transparentIndex) {
                            $transparentColor = false;
                            if ($transparentIndex >=0 && $transparentIndex <= imagecolorstotal($this->_imageHandler)) {
                                list($r, $g, $b)  = array_values(imagecolorsforindex($this->_imageHandler, $transparentIndex));
                                $transparentColor = imagecolorallocate($imageResourceTo, $r, $g, $b);
                            }
                            if (false === $transparentColor) {
                                throw new Exception('Failed to allocate transparent color for image.');
                            }
                            if (!imagefill($imageResourceTo, 0, 0, $transparentColor)) {
                                throw new Exception('Failed to fill image with transparency.');
                            }
                            imagecolortransparent($imageResourceTo, $transparentColor);
                            return $transparentColor;
                        }
                    }
                    catch (Exception $e) {
                        // fallback to default background color
                    }
                }
                list($r, $g, $b) = $this->_backgroundColor;
                $color = imagecolorallocate($imageResourceTo, $r, $g, $b);
                if (!imagefill($imageResourceTo, 0, 0, $color)) {
                    throw new Exception("Failed to fill image background with color {$r} {$g} {$b}.");
                }

                return $color;
            }

            /**
             * Gives true for a PNG with alpha, false otherwise
             *
             * @param string $fileName
             * @return boolean
             */

            public function checkAlpha($fileName)
            {
                return ((ord(file_get_contents($fileName, false, null, 25, 1)) & 6) & 4) == 4;
            }

            private function _getTransparency($imageResource, $fileType, &$isAlpha = false, &$isTrueColor = false)
            {
                $isAlpha     = false;
                $isTrueColor = false;
                // assume that transparency is supported by gif/png only
                if ((IMAGETYPE_GIF === $fileType) || (IMAGETYPE_PNG === $fileType)) {
                    // check for specific transparent color
                    $transparentIndex = imagecolortransparent($imageResource);
                    if ($transparentIndex >= 0) {
                        return $transparentIndex;
                    }
                    // assume that truecolor PNG has transparency
                    elseif (IMAGETYPE_PNG === $fileType) {
                        $isAlpha     = $this->checkAlpha($this->_fileName);
                        $isTrueColor = true;
                        return $transparentIndex; // -1
                    }
                }
                if (IMAGETYPE_JPEG === $fileType) {
                    $isTrueColor = true;
                }
                return false;
            }

            /**
             * Change the image size
             *
             * @param int $frameWidth
             * @param int $frameHeight
             */
            public function resize($frameWidth = null, $frameHeight = null)
            {
                if (empty($frameWidth) && empty($frameHeight)) {
                    throw new Exception('Invalid image dimensions.');
                }

                // calculate lacking dimension
                if (!$this->_keepFrame) {
                    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;
                $dstX = 0;
                $dstY = 0;
                $dstWidth  = $frameWidth;
                $dstHeight = $frameHeight;
                if ($this->_keepAspectRatio) {
                    // 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);
                    }
                }
                // 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;
                }

                // create new image
                $isAlpha     = false;
                $isTrueColor = false;
                $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha, $isTrueColor);
                if ($isTrueColor) {
                    $newImage = imagecreatetruecolor($frameWidth, $frameHeight);
                }
                else {
                    $newImage = imagecreate($frameWidth, $frameHeight);
                }

                // fill new image with required color
                $this->_fillBackgroundColor($newImage);

                // resample source image and copy it into new frame
                imagecopyresampled(
                    $newImage,
                    $this->_imageHandler,
                    $dstX, $dstY,
                    $srcX, $srcY,
                    $dstWidth, $dstHeight,
                    $this->_imageSrcWidth, $this->_imageSrcHeight
                );
                $this->_imageHandler = $newImage;
                $this->refreshImageDimensions();
                $this->_resized = true;
            }

            public function rotate($angle)
            {
        /*
                $isAlpha = false;
                $backgroundColor = $this->_getTransparency($this->_imageHandler, $this->_fileType, $isAlpha);
                list($r, $g, $b) = $this->_backgroundColor;
                if ($isAlpha) {
                    $backgroundColor = imagecolorallocatealpha($this->_imageHandler, 0, 0, 0, 127);
                }
                elseif (false === $backgroundColor) {
                    $backgroundColor = imagecolorallocate($this->_imageHandler, $r, $g, $b);
                }
                $this->_imageHandler = imagerotate($this->_imageHandler, $angle, $backgroundColor);
        //*/
                $this->_imageHandler = imagerotate($this->_imageHandler, $angle, $this->imageBackgroundColor);
                $this->refreshImageDimensions();
            }

            public function watermark($watermarkImage, $positionX=0, $positionY=0, $watermarkImageOpacity=30, $repeat=false)
            {
                list($watermarkSrcWidth, $watermarkSrcHeight, $watermarkFileType, ) = getimagesize($watermarkImage);
                $this->_getFileAttributes();
                $watermark = call_user_func($this->_getCallback(
                    'create',
                    $watermarkFileType,
                    'Unsupported watermark image format.'
                ), $watermarkImage);

                $merged = false;

                if ($this->getWatermarkWidth() &&
                    $this->getWatermarkHeigth() &&
                    ($this->getWatermarkPosition() != self::POSITION_STRETCH)
                ) {
                    $newWatermark = imagecreatetruecolor($this->getWatermarkWidth(), $this->getWatermarkHeigth());
                    imagealphablending($newWatermark, false);
                    $col = imagecolorallocate($newWatermark, 255, 255, 255);
                    imagecolortransparent($newWatermark, $col);
                    imagefilledrectangle($newWatermark, 0, 0, $this->getWatermarkWidth(), $this->getWatermarkHeigth(), $col);
                    imagealphablending($newWatermark, true);
                    imageSaveAlpha($newWatermark, true);
                    imagecopyresampled(
                        $newWatermark,
                        $watermark,
                        0, 0, 0, 0,
                        $this->getWatermarkWidth(), $this->getWatermarkHeigth(),
                        imagesx($watermark), imagesy($watermark)
                    );
                    $watermark = $newWatermark;
                }

                if( $this->getWatermarkPosition() == self::POSITION_TILE ) {
                    $repeat = true;
                } elseif( $this->getWatermarkPosition() == self::POSITION_STRETCH ) {

                    $newWatermark = imagecreatetruecolor($this->_imageSrcWidth, $this->_imageSrcHeight);
                    imagealphablending($newWatermark, false);
                    $col = imagecolorallocate($newWatermark, 255, 255, 255);
                    imagecolortransparent($newWatermark, $col);
                    imagefilledrectangle($newWatermark, 0, 0, $this->_imageSrcWidth, $this->_imageSrcHeight, $col);
                    imagealphablending($newWatermark, true);
                    imageSaveAlpha($newWatermark, true);
                    imagecopyresampled(
                        $newWatermark,
                        $watermark,
                        0, 0, 0, 0,
                        $this->_imageSrcWidth, $this->_imageSrcHeight,
                        imagesx($watermark), imagesy($watermark)
                    );
                    $watermark = $newWatermark;

                } elseif( $this->getWatermarkPosition() == self::POSITION_CENTER ) {
                    $positionX = ($this->_imageSrcWidth/2 - imagesx($watermark)/2);
                    $positionY = ($this->_imageSrcHeight/2 - imagesy($watermark)/2);
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_RIGHT ) {
                    $positionX = ($this->_imageSrcWidth - imagesx($watermark));
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                } elseif( $this->getWatermarkPosition() == self::POSITION_TOP_LEFT  ) {
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_RIGHT ) {
                    $positionX = ($this->_imageSrcWidth - imagesx($watermark));
                    $positionY = ($this->_imageSrcHeight - imagesy($watermark));
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                } elseif( $this->getWatermarkPosition() == self::POSITION_BOTTOM_LEFT ) {
                    $positionY = ($this->_imageSrcHeight - imagesy($watermark));
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                }

                if( $repeat === false && $merged === false ) {
                    imagecopymerge(
                        $this->_imageHandler,
                        $watermark,
                        $positionX, $positionY,
                        0, 0,
                        imagesx($watermark), imagesy($watermark),
                        $this->getWatermarkImageOpacity()
                    );
                } else {
                    $offsetX = $positionX;
                    $offsetY = $positionY;
                    while( $offsetY <= ($this->_imageSrcHeight+imagesy($watermark)) ) {
                        while( $offsetX <= ($this->_imageSrcWidth+imagesx($watermark)) ) {
                            imagecopymerge(
                                $this->_imageHandler,
                                $watermark,
                                $offsetX, $offsetY,
                                0, 0,
                                imagesx($watermark), imagesy($watermark),
                                $this->getWatermarkImageOpacity()
                            );
                            $offsetX += imagesx($watermark);
                        }
                        $offsetX = $positionX;
                        $offsetY += imagesy($watermark);
                    }
                }

                imagedestroy($watermark);
                $this->refreshImageDimensions();
            }

            public function crop($top=0, $left=0, $right=0, $bottom=0)
            {
                if( $left == 0 && $top == 0 && $right == 0 && $bottom == 0 ) {
                    return;
                }

                $newWidth = $this->_imageSrcWidth - $left - $right;
                $newHeight = $this->_imageSrcHeight - $top - $bottom;

                $canvas = imagecreatetruecolor($newWidth, $newHeight);

                if ($this->_fileType == IMAGETYPE_PNG) {
                    $this->_saveAlpha($canvas);
                }

                imagecopyresampled(
                    $canvas,
                    $this->_imageHandler,
                    0, 0, $left, $top,
                    $newWidth, $newHeight,
                    $newWidth, $newHeight
                );

                $this->_imageHandler = $canvas;
                $this->refreshImageDimensions();
            }

            public function checkDependencies()
            {
                foreach( $this->_requiredExtensions as $value ) {
                    if( !extension_loaded($value) ) {
                        throw new Exception("Required PHP extension '{$value}' was not loaded.");
                    }
                }
            }

            private function refreshImageDimensions()
            {
                $this->_imageSrcWidth = imagesx($this->_imageHandler);
                $this->_imageSrcHeight = imagesy($this->_imageHandler);
            }

            function __destruct()
            {
                @imagedestroy($this->_imageHandler);
            }

            /*
             * Fixes saving PNG alpha channel
             */
            private function _saveAlpha($imageHandler)
            {
                $background = imagecolorallocate($imageHandler, 0, 0, 0);
                ImageColorTransparent($imageHandler, $background);
                imagealphablending($imageHandler, false);
                imagesavealpha($imageHandler, true);
            }
        }
  • 写回答

1条回答 默认 最新

  • dpgjci27392 2014-12-12 11:05
    关注

    Have you tried the hackathon magento imagemagick enabler?

    [https://github.com/magento-hackathon/Perfect_Watermarks][1]

    I am going to test this in a minute, so this suggestion is absolutly untested at the moment.

    评论

报告相同问题?

悬赏问题

  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘
  • ¥15 perl MISA分析p3_in脚本出错
  • ¥15 k8s部署jupyterlab,jupyterlab保存不了文件
  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?