Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php/* vim: set expandtab tabstop=4 shiftwidth=4: *//*** GD implementation for Image_Transform package** PHP versions 4 and 5** LICENSE: This source file is subject to version 3.0 of the PHP license* that is available through the world-wide-web at the following URI:* http://www.php.net/license/3_0.txt. If you did not receive a copy of* the PHP License and are unable to obtain it through the web, please* send a note to license@php.net so we can mail you a copy immediately.** @category Image* @package Image_Transform* @subpackage Image_Transform_Driver_GD* @author Alan Knowles <alan@akbkhome.com>* @author Peter Bowyer <peter@mapledesign.co.uk>* @author Philippe Jausions <Philippe.Jausions@11abacus.com>* @copyright 2002-2005 The PHP Group* @license http://www.php.net/license/3_0.txt PHP License 3.0* @version CVS: $Id: GD.php,v 1.32 2007/04/19 16:36:09 dufuz Exp $* @link http://pear.php.net/package/Image_Transform*/require_once 'Image/Transform.php';/*** GD implementation for Image_Transform package** Usage :* $img =& Image_Transform::factory('GD');* $angle = -78;* $img->load('magick.png');** if ($img->rotate($angle, array(* 'autoresize' => true,* 'color_mask' => array(255, 0, 0)))) {* $img->addText(array(* 'text' => 'Rotation ' . $angle,* 'x' => 0,* 'y' => 100,* 'font' => '/usr/share/fonts/default/TrueType/cogb____.ttf'));* $img->display();* } else {* echo "Error";* }* $img->free();** @category Image* @package Image_Transform* @subpackage Image_Transform_Driver_GD* @author Alan Knowles <alan@akbkhome.com>* @author Peter Bowyer <peter@mapledesign.co.uk>* @author Philippe Jausions <Philippe.Jausions@11abacus.com>* @copyright 2002-2005 The PHP Group* @license http://www.php.net/license/3_0.txt PHP License 3.0* @version Release: @package_version@* @link http://pear.php.net/package/Image_Transform* @since PHP 4.0*/class Image_Transform_Driver_GD extends Image_Transform{/*** Holds the image resource for manipulation** @var resource $imageHandle* @access protected*/var $imageHandle = null;/*** Holds the original image file** @var resource $imageHandle* @access protected*/var $old_image = null;/*** Check settings*/function Image_Transform_Driver_GD(){$this->__construct();} // End function Image/*** Check settings** @since PHP 5*/function __construct(){if (!PEAR::loadExtension('gd')) {$this->isError(PEAR::raiseError("GD library is not available.",IMAGE_TRANSFORM_ERROR_UNSUPPORTED));} else {$types = ImageTypes();if ($types & IMG_PNG) {$this->_supported_image_types['png'] = 'rw';}if (($types & IMG_GIF)|| function_exists('imagegif')) {$this->_supported_image_types['gif'] = 'rw';} elseif (function_exists('imagecreatefromgif')) {$this->_supported_image_types['gif'] = 'r';}if ($types & IMG_JPG) {$this->_supported_image_types['jpeg'] = 'rw';}if ($types & IMG_WBMP) {$this->_supported_image_types['wbmp'] = 'rw';}if (!$this->_supported_image_types) {$this->isError(PEAR::raiseError("No supported image types available", IMAGE_TRANSFORM_ERROR_UNSUPPORTED));}}} // End function Image/*** Loads an image from file** @param string $image filename* @return bool|PEAR_Error TRUE or a PEAR_Error object on error* @access public*/function load($image){$this->free();$this->image = $image;$result = $this->_get_image_details($image);if (PEAR::isError($result)) {return $result;}if (!$this->supportsType($this->type, 'r')) {return PEAR::raiseError('Image type not supported for input',IMAGE_TRANSFORM_ERROR_UNSUPPORTED);}$functionName = 'ImageCreateFrom' . $this->type;$this->imageHandle = $functionName($this->image);if (!$this->imageHandle) {$this->imageHandle = null;return PEAR::raiseError('Error while loading image file.',IMAGE_TRANSFORM_ERROR_IO);}return true;} // End load/*** Adds a border of constant width around an image** @param int $border_width Width of border to add* @author Peter Bowyer* @return bool TRUE* @access public*/function addBorder($border_width, $color = ''){$this->new_x = $this->img_x + 2 * $border_width;$this->new_y = $this->img_y + 2 * $border_width;$new_img = $this->_createImage($new_x, $new_y, $this->true_color);$options = array('pencilColor', $color);$color = $this->_getColor('pencilColor', $options, array(0, 0, 0));if ($color) {if ($this->true_color) {$c = imagecolorresolve($this->imageHandle, $color[0], $color[1], $color[2]);imagefill($new_img, 0, 0, $c);} else {imagecolorset($new_img, imagecolorat($new_img, 0, 0), $color[0], $color[1], $color[2]);}}ImageCopy($new_img, $this->imageHandle, $border_width, $border_width, 0, 0, $this->img_x, $this->img_y);$this->imageHandle = $new_img;$this->resized = true;return true;}/*** addText** @param array $params Array contains options* array(* 'text' The string to draw* 'x' Horizontal position* 'y' Vertical Position* 'color' Font color* 'font' Font to be used* 'size' Size of the fonts in pixel* 'resize_first' Tell if the image has to be resized* before drawing the text* )** @return bool|PEAR_Error TRUE or a PEAR_Error object on error*/function addText($params){$params = array_merge($this->_get_default_text_params(), $params);extract($params);$options = array('fontColor' => $color);$color = $this->_getColor('fontColor', $options, array(0, 0, 0));$c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);if ('ttf' == substr($font, -3)) {ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);} else {ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);}return true;} // End addText/*** Rotates image by the given angle** Uses a fast rotation algorythm for custom angles* or lines copy for multiple of 90 degrees** @param int $angle Rotation angle* @param array $options array(* 'canvasColor' => array(r ,g, b), named color or #rrggbb* )* @author Pierre-Alain Joye* @return bool|PEAR_Error TRUE or a PEAR_Error object on error* @access public*/function rotate($angle, $options = null){if (($angle % 360) == 0) {return true;}$color_mask = $this->_getColor('canvasColor', $options,array(255, 255, 255));$mask = imagecolorresolve($this->imageHandle, $color_mask[0], $color_mask[1], $color_mask[2]);$this->old_image = $this->imageHandle;// Multiply by -1 to change the sign, so the image is rotated clockwise$this->imageHandle = ImageRotate($this->imageHandle, $angle * -1, $mask);return true;}/*** Horizontal mirroring** @return mixed TRUE or PEAR_Error object on error* @access public* @see flip()**/function mirror(){$new_img = $this->_createImage();for ($x = 0; $x < $this->new_x; ++$x) {imagecopy($new_img, $this->imageHandle, $x, 0,$this->new_x - $x - 1, 0, 1, $this->new_y);}imagedestroy($this->imageHandle);$this->imageHandle = $new_img;return true;}/*** Vertical mirroring** @return TRUE or PEAR Error object on error* @access public* @see mirror()**/function flip(){$new_img = $this->_createImage();for ($y = 0; $y < $this->new_y; ++$y) {imagecopy($new_img, $this->imageHandle, 0, $y,0, $this->new_y - $y - 1, $this->new_x, 1);}imagedestroy($this->imageHandle);$this->imageHandle = $new_img;/* for very large images we may want to use the followingNeeds to find out what is the threshholdfor ($x = 0; $x < $this->new_x; ++$x) {for ($y1 = 0; $y1 < $this->new_y / 2; ++$y1) {$y2 = $this->new_y - 1 - $y1;$color1 = imagecolorat($this->imageHandle, $x, $y1);$color2 = imagecolorat($this->imageHandle, $x, $y2);imagesetpixel($this->imageHandle, $x, $y1, $color2);imagesetpixel($this->imageHandle, $x, $y2, $color1);}} */return true;}/*** Crops image by size and start coordinates** @param int width Cropped image width* @param int height Cropped image height* @param int x X-coordinate to crop at* @param int y Y-coordinate to crop at* @return bool|PEAR_Error TRUE or a PEAR_Error object on error* @access public*/function crop($width, $height, $x = 0, $y = 0){// Sanity checkif (!$this->intersects($width, $height, $x, $y)) {return PEAR::raiseError('Nothing to crop', IMAGE_TRANSFORM_ERROR_OUTOFBOUND);}$x = min($this->new_x, max(0, $x));$y = min($this->new_y, max(0, $y));$width = min($width, $this->new_x - $x);$height = min($height, $this->new_y - $y);$new_img = $this->_createImage($width, $height);if (!imagecopy($new_img, $this->imageHandle, 0, 0, $x, $y, $width, $height)) {imagedestroy($new_img);return PEAR::raiseError('Failed transformation: crop()',IMAGE_TRANSFORM_ERROR_FAILED);}$this->old_image = $this->imageHandle;$this->imageHandle = $new_img;$this->resized = true;$this->new_x = $width;$this->new_y = $height;return true;}/*** Converts the image to greyscale** @return bool|PEAR_Error TRUE or a PEAR_Error object on error* @access public*/function greyscale() {imagecopymergegray($this->imageHandle, $this->imageHandle, 0, 0, 0, 0, $this->new_x, $this->new_y, 0);return true;}/*** Resize Action** For GD 2.01+ the new copyresampled function is used* It uses a bicubic interpolation algorithm to get far* better result.** Options:* - scaleMethod: "pixel" or "smooth"** @param int $new_x New width* @param int $new_y New height* @param mixed $options Optional parameters** @return bool|PEAR_Error TRUE on success or PEAR_Error object on error* @access protected*/function _resize($new_x, $new_y, $options = null){if ($this->resized === true) {return PEAR::raiseError('You have already resized the image without saving it. Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);}if ($this->new_x == $new_x && $this->new_y == $new_y) {return true;}$scaleMethod = $this->_getOption('scaleMethod', $options, 'smooth');// Make sure to get a true color image if doing resampled resizing// otherwise get the same type of image$trueColor = ($scaleMethod == 'pixel') ? null : true;$new_img = $this->_createImage($new_x, $new_y, $trueColor);$icr_res = null;if ($scaleMethod != 'pixel' && function_exists('ImageCopyResampled')) {$icr_res = ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);}if (!$icr_res) {ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);}$this->old_image = $this->imageHandle;$this->imageHandle = $new_img;$this->resized = true;$this->new_x = $new_x;$this->new_y = $new_y;return true;}/*** Adjusts the image gamma** @param float $outputgamma** @return bool|PEAR_Error TRUE or a PEAR_Error object on error* @access public*/function gamma($outputgamma = 1.0){if ($outputgamma != 1.0) {ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);}return true;}/*** Helper method to save to a file or output the image** @param string $filename the name of the file to write to (blank to output)* @param string $types define the output format, default* is the current used format* @param int $quality output DPI, default is 75** @return bool|PEAR_Error TRUE on success or PEAR_Error object on error* @access protected*/function _generate($filename, $type = '', $quality = null){$type = strtolower(($type == '') ? $this->type : $type);$options = (is_array($quality)) ? $quality : array();switch ($type) {case 'jpg':$type = 'jpeg';case 'jpeg':if (is_numeric($quality)) {$options['quality'] = $quality;}$quality = $this->_getOption('quality', $options, 75);break;}if (!$this->supportsType($type, 'w')) {return PEAR::raiseError('Image type not supported for output',IMAGE_TRANSFORM_ERROR_UNSUPPORTED);}if ($filename == '') {header('Content-type: ' . $this->getMimeType($type));$action = 'output image';} else {$action = 'save image to file';}$functionName = 'image' . $type;switch ($type) {case 'jpeg':$result = $functionName($this->imageHandle, $filename, $quality);break;default:if ($filename == '') {$result = $functionName($this->imageHandle);} else {$result = $functionName($this->imageHandle, $filename);}}if (!$result) {return PEAR::raiseError('Couldn\'t ' . $action,IMAGE_TRANSFORM_ERROR_IO);}$this->imageHandle = $this->old_image;if (!$this->keep_settings_on_save) {$this->free();}return true;} // End save/*** Displays image without saving and lose changes.** This method adds the Content-type HTTP header** @param string $type (JPEG, PNG...);* @param int $quality 75** @return bool|PEAR_Error TRUE or PEAR_Error object on error* @access public*/function display($type = '', $quality = null){return $this->_generate('', $type, $quality);;}/*** Saves the image to a file** @param string $filename the name of the file to write to* @param string $type the output format, default* is the current used format* @param int $quality default is 75** @return bool|PEAR_Error TRUE on success or PEAR_Error object on error* @access public*/function save($filename, $type = '', $quality = null){if (!trim($filename)) {return PEAR::raiseError('Filename missing',IMAGE_TRANSFORM_ERROR_ARGUMENT);}return $this->_generate($filename, $type, $quality);}/*** Destroys image handle** @access public*/function free(){$this->resized = false;if (is_resource($this->imageHandle)) {ImageDestroy($this->imageHandle);}$this->imageHandle = null;if (is_resource($this->old_image)){ImageDestroy($this->old_image);}$this->old_image = null;}/*** Returns a new image for temporary processing** @param int $width width of the new image* @param int $height height of the new image* @param bool $trueColor force which type of image to create* @return resource a GD image resource* @access protected*/function _createImage($width = -1, $height = -1, $trueColor = null){if ($width == -1) {$width = $this->new_x;}if ($height == -1) {$height = $this->new_y;}$new_img = null;if (is_null($trueColor)) {if (function_exists('imageistruecolor')) {$createtruecolor = imageistruecolor($this->imageHandle);} else {$createtruecolor = true;}} else {$createtruecolor = $trueColor;}if ($createtruecolor&& function_exists('ImageCreateTrueColor')) {$new_img = @ImageCreateTrueColor($width, $height);}if (!$new_img) {$new_img = ImageCreate($width, $height);imagepalettecopy($new_img, $this->imageHandle);$color = imagecolortransparent($this->imageHandle);if ($color != -1) {imagecolortransparent($new_img, $color);imagefill($new_img, 0, 0, $color);}}return $new_img;}}