Image_Transform
[ class tree: Image_Transform ] [ index: Image_Transform ] [ all elements ]

Source for file Transform.php

Documentation is available at Transform.php

  1. <?php
  2.  
  3. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  4.  
  5. /**
  6.  * Simple and cross-library package to doing image transformations and
  7.  * manipulations.
  8.  *
  9.  * PHP versions 4 and 5
  10.  *
  11.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  12.  * that is available through the world-wide-web at the following URI:
  13.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  14.  * the PHP License and are unable to obtain it through the web, please
  15.  * send a note to license@php.net so we can mail you a copy immediately.
  16.  *
  17.  * @category   Image
  18.  * @package    Image_Transform
  19.  * @author     Vincent Oostindie <vincent@sunlight.tmfweb.nl>
  20.  * @author     Alan Knowles <alan@akbkhome.com>
  21.  * @author     Peter Bowyer <peter@mapledesign.co.uk>
  22.  * @author     Philippe Jausions <Philippe.Jausions@11abacus.com>
  23.  * @copyright  2002-2007 The PHP Group
  24.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  25.  * @version    CVS: $Id: Transform.php,v 1.42 2007/04/19 16:17:57 dufuz Exp $
  26.  * @link       http://pear.php.net/package/Image_Transform
  27.  */
  28.  
  29. /**
  30.  * Include for error handling
  31.  */
  32. require_once 'PEAR.php';
  33.  
  34. /**
  35.  * Error code for unsupported library, image format or methods
  36.  */
  37. define('IMAGE_TRANSFORM_ERROR_UNSUPPORTED'1);
  38.  
  39. /**
  40.  * Error code for failed transformation operations
  41.  */
  42. define('IMAGE_TRANSFORM_ERROR_FAILED'2);
  43.  
  44. /**
  45.  * Error code for failed i/o (Input/Output) operations
  46.  */
  47. define('IMAGE_TRANSFORM_ERROR_IO'3);
  48.  
  49. /**
  50.  * Error code for invalid arguments
  51.  */
  52. define('IMAGE_TRANSFORM_ERROR_ARGUMENT'4);
  53.  
  54. /**
  55.  * Error code for out-of-bound related errors
  56.  */
  57. define('IMAGE_TRANSFORM_ERROR_OUTOFBOUND'5);
  58.  
  59.  
  60.  
  61. /**
  62.  * Base class with factory method for backend driver
  63.  *
  64.  * The main "Image_Transform" class is a container and base class which
  65.  * provides a static method for creating an Image object as well as
  66.  * some utility functions (maths) common to all parts of Image_Transform.
  67.  *
  68.  * @category   Image
  69.  * @package    Image_Transform
  70.  * @author     Alan Knowles <alan@akbkhome.com>
  71.  * @author     Peter Bowyer <peter@mapledesign.co.uk>
  72.  * @author     Philippe Jausions <Philippe.Jausions@11abacus.com>
  73.  * @copyright  2002-2007 The PHP Group
  74.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  75.  * @version    Release: @package_version@
  76.  * @link       http://pear.php.net/package/Image_Transform
  77.  * @since      PHP 4.0
  78.  */
  79. {
  80.     /**
  81.      * Name of the image file
  82.      * @var string 
  83.      */
  84.     var $image = '';
  85.  
  86.     /**
  87.      * Type of the image file (eg. jpg, gif png ...)
  88.      * @var string 
  89.      */
  90.     var $type = '';
  91.  
  92.     /**
  93.      * Original image width in x direction
  94.      * @var int 
  95.      */
  96.     var $img_x = '';
  97.  
  98.     /**
  99.      * Original image width in y direction
  100.      * @var int 
  101.      */
  102.     var $img_y = '';
  103.  
  104.     /**
  105.      * New image width in x direction
  106.      * @var int 
  107.      */
  108.     var $new_x = '';
  109.  
  110.     /**
  111.      * New image width in y direction
  112.      * @var int 
  113.      */
  114.     var $new_y = '';
  115.  
  116.     /**
  117.      * Path to the library used
  118.      * e.g. /usr/local/ImageMagick/bin/ or
  119.      * /usr/local/netpbm/
  120.      */
  121.     var $lib_path = '';
  122.  
  123.     /**
  124.      * Flag to warn if image has been resized more than once before displaying
  125.      * or saving.
  126.      */
  127.     var $resized = false;
  128.  
  129.     /**
  130.      * @var array General options
  131.      * @access protected
  132.      */
  133.     var $_options = array(
  134.         'quality'     => 75,
  135.         'scaleMethod' => 'smooth',
  136.         'canvasColor' => array(255255255),
  137.         'pencilColor' => array(000),
  138.         'textColor'   => array(000)
  139.         );
  140.  
  141.     /**
  142.      * Flag for whether settings should be discarded on saving/display of image
  143.      * @var bool 
  144.      * @see Image_Transform::keepSettingsOnSave
  145.      */
  146.     var $keep_settings_on_save = false;
  147.  
  148.     /**
  149.      * Supported image types
  150.      * @var array 
  151.      * @access protected
  152.      */
  153.     var $_supported_image_types = array();
  154.  
  155.     /**
  156.      * Initialization error tracking
  157.      * @var object 
  158.      * @access private
  159.      ***/
  160.     var $_error = null;
  161.  
  162.     /**
  163.      * associative array that tracks existence of programs
  164.      * (for drivers using shell interface and a tiny performance
  165.      * improvement if the clearstatcache() is used)
  166.      * @var array 
  167.      * @access protected
  168.      */
  169.     var $_programs = array();
  170.  
  171.      /**
  172.       * Default parameters used in the addText methods.
  173.       */
  174.      var $default_text_params = array('text' => 'Default text',
  175.                                       'x'     => 10,
  176.                                       'y'     => 20,
  177.                                       'color' => 'red',
  178.                                       'font'  => 'Arial.ttf',
  179.                                       'size'  => '12',
  180.                                       'angle' => 0,
  181.                                       'resize_first' => false);
  182.  
  183.     /**
  184.      * Creates a new Image_Transform object
  185.      *
  186.      * @param string $driver name of driver class to initialize. If no driver
  187.      *                is specified the factory will attempt to use 'Imagick' first
  188.      *                then 'GD' second, then 'Imlib' last
  189.      *
  190.      * @return object an Image_Transform object, or PEAR_Error on error
  191.      *
  192.      * @see PEAR::isError()
  193.      * @see Image_Transform::setOption()
  194.      */
  195.     function &factory($driver '')
  196.     {
  197.         if ($driver == ''{
  198.             $extensions = array(
  199.                 'imagick' => 'Imagick2',
  200.                 'gd'      => 'GD',
  201.                 'imlib'   => 'Imlib');
  202.  
  203.             foreach ($extensions as $ext => $ext_driver{
  204.                 if (PEAR::loadExtension($ext)) {
  205.                     $driver $ext_driver;
  206.                     break;
  207.                 }
  208.             }
  209.             if (!$driver{
  210.                 return PEAR::raiseError('No image library specified and none can be found.  You must specify driver in factory() call.',
  211.                     IMAGE_TRANSFORM_ERROR_ARGUMENT);
  212.             }
  213.         }
  214.         @include_once 'Image/Transform/Driver/' basename($driver'.php';
  215.  
  216.         $classname = "Image_Transform_Driver_{$driver}";
  217.         if (!class_exists($classname)) {
  218.             return PEAR::raiseError('Image library not supported... aborting.',
  219.                 IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
  220.         }
  221.         $obj =new $classname;
  222.  
  223.         // Check startup error
  224.         if ($error =$obj->isError()) {
  225.             $obj =$error;
  226.         }
  227.         return $obj;
  228.     }
  229.  
  230.     /**
  231.      * Returns/sets an error when the instance couldn't initialize properly
  232.      *
  233.      * @param  object PEAR_Error object when setting an error
  234.      * @return mixed FALSE or PEAR_Error object
  235.      * @access protected
  236.      */
  237.     function &isError($error = null)
  238.     {
  239.         if (!is_null($error)) {
  240.             $this->_error =$error;
  241.         }
  242.         return $this->_error;
  243.     }
  244.  
  245.     /**
  246.      * Resizes the image in the X and/or Y direction(s)
  247.      *
  248.      * If either is 0 it will keep the original size for that dimension
  249.      *
  250.      * @param mixed $new_x (0, number, percentage 10% or 0.1)
  251.      * @param mixed $new_y (0, number, percentage 10% or 0.1)
  252.      * @param array $options Options
  253.      * @return mixed TRUE or PEAR_Error object on error
  254.      * @access public
  255.      */
  256.     function resize($new_x = 0$new_y = 0$options = null)
  257.     {
  258.         // 0 means keep original size
  259.         $new_x (0 == $new_x)
  260.                  ? $this->img_x
  261.                  : $this->_parse_size($new_x$this->img_x);
  262.         $new_y (0 == $new_y)
  263.                  ? $this->img_y
  264.                  : $this->_parse_size($new_y$this->img_y);
  265.  
  266.         // Now do the library specific resizing.
  267.         return $this->_resize($new_x$new_y$options);
  268.     // End resize
  269.  
  270.  
  271.     
  272.     /**
  273.      * Scales the image to the specified width
  274.      *
  275.      * This method preserves the aspect ratio
  276.      *
  277.      * @param int $new_x Size to scale X-dimension to
  278.      * @return mixed TRUE or PEAR_Error object on error
  279.      * @access public
  280.      */
  281.     function scaleByX($new_x)
  282.     {
  283.         if ($new_x <= 0{
  284.             return PEAR::raiseError('New size must be strictly positive',
  285.                                         IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
  286.         }
  287.         $new_y round(($new_x $this->img_x$this->img_y0);
  288.         return $this->_resize(max(1$new_x)max(1$new_y));
  289.     // End scaleByX
  290.  
  291.     
  292.     /**
  293.      * Alias for resize()
  294.      *
  295.      * @see resize()
  296.      */
  297.     function scaleByXY($new_x = 0$new_y = 0$options = null)
  298.     {
  299.         return $this->resize($new_x$new_y$options);
  300.     // End scaleByXY
  301.  
  302.     
  303.     /**
  304.      * Scales the image to the specified height.
  305.      *
  306.      * This method preserves the aspect ratio
  307.      *
  308.      * @param int $new_y Size to scale Y-dimension to
  309.      * @return mixed TRUE or PEAR_Error object on error
  310.      * @access public
  311.      */
  312.     function scaleByY($new_y)
  313.     {
  314.         if ($new_y <= 0{
  315.             return PEAR::raiseError('New size must be strictly positive',
  316.                                         IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
  317.         }
  318.         $new_x round(($new_y $this->img_y$this->img_x0);
  319.         return $this->_resize(max(1$new_x)max(1$new_y));
  320.     // End scaleByY
  321.  
  322.     
  323.     /**
  324.      * Scales an image by a percentage, factor or a given length
  325.      *
  326.      * This method preserves the aspect ratio
  327.      *
  328.      * @param mixed (number, percentage 10% or 0.1)
  329.      * @return mixed TRUE or PEAR_Error object on error
  330.      * @access public
  331.      * @see scaleByPercentage, scaleByFactor, scaleByLength
  332.      */
  333.     function scale($size)
  334.     {
  335.         if ((strlen($size> 1&& (substr($size-1== '%')) {
  336.             return $this->scaleByPercentage(substr($size0-1));
  337.         elseif ($size < 1{
  338.             return $this->scaleByFactor($size);
  339.         else {
  340.             return $this->scaleByLength($size);
  341.         }
  342.     // End scale
  343.  
  344.     
  345.     /**
  346.      * Scales an image to a percentage of its original size.  For example, if
  347.      * my image was 640x480 and I called scaleByPercentage(10) then the image
  348.      * would be resized to 64x48
  349.      *
  350.      * @param  int $size Percentage of original size to scale to
  351.      * @return mixed TRUE or PEAR_Error object on error
  352.      * @access public
  353.      */
  354.     function scaleByPercentage($size)
  355.     {
  356.         return $this->scaleByFactor($size / 100);
  357.     // End scaleByPercentage
  358.  
  359.     
  360.     /**
  361.      * Scales an image to a factor of its original size.  For example, if
  362.      * my image was 640x480 and I called scaleByFactor(0.5) then the image
  363.      * would be resized to 320x240.
  364.      *
  365.      * @param float $size Factor of original size to scale to
  366.      * @return mixed TRUE or PEAR_Error object on error
  367.      * @access public
  368.      */
  369.     function scaleByFactor($size)
  370.     {
  371.         if ($size <= 0{
  372.             return PEAR::raiseError('New size must be strictly positive',
  373.                                         IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
  374.         }
  375.         $new_x round($size $this->img_x0);
  376.         $new_y round($size $this->img_y0);
  377.         return $this->_resize(max(1$new_x)max(1$new_y));
  378.     // End scaleByFactor
  379.  
  380.     
  381.     /**
  382.      * Scales an image so that the longest side has the specified dimension.
  383.      *
  384.      * This method preserves the aspect ratio
  385.      *
  386.      * @param int $size Max dimension in pixels
  387.      * @return mixed TRUE or PEAR_Error object on error
  388.      * @access public
  389.      */
  390.     function scaleMaxLength($size)
  391.     {
  392.         if ($size <= 0{
  393.             return PEAR::raiseError('New size must be strictly positive',
  394.                                         IMAGE_TRANSFORM_ERROR_OUTOFBOUND);
  395.         }
  396.         if ($this->img_x >= $this->img_y{
  397.             $new_x $size;
  398.             $new_y round(($new_x $this->img_x$this->img_y0);
  399.         else {
  400.             $new_y $size;
  401.             $new_x round(($new_y $this->img_y$this->img_x0);
  402.         }
  403.         return $this->_resize(max(1$new_x)max(1$new_y));
  404.     // End scaleMaxLength
  405.  
  406.     
  407.     /**
  408.      * Alias for scaleMaxLength
  409.      *
  410.      * @return mixed TRUE or PEAR_Error object on error
  411.      * @access public
  412.      * @see scaleMaxLength()
  413.      */
  414.     function scaleByLength($size)
  415.     {
  416.         return $this->scaleMaxLength($size);
  417.     }
  418.  
  419.     /**
  420.      * Fits the image in the specified box size
  421.      *
  422.      * If the image is bigger than the box specified by $width and $height,
  423.      * it will be scaled down to fit inside of it.
  424.      * If the image is smaller, nothing is done.
  425.      *
  426.      * @param  integer $width 
  427.      * @param  integer $height 
  428.      * @return bool|PEAR_ErrorTRUE or PEAR_Error object on error
  429.      * @access public
  430.      */
  431.     function fit($width$height)
  432.     {
  433.         if ($width <= 0 || $height <= 0{
  434.             return PEAR::raiseError("Invalid arguments.",
  435.                 IMAGE_TRANSFORM_ERROR_ARGUMENT);
  436.         }
  437.         $x $this->img_x / $width;
  438.         $y $this->img_y / $height;
  439.         if ($x <= 1 && $y <= 1{
  440.             return true;
  441.         elseif ($x $y{
  442.             return $this->scaleByX($width);
  443.         else {
  444.             return $this->scaleByY($height);
  445.         }
  446.     }
  447.  
  448.     /**
  449.      * Fits the image in the specified width
  450.      *
  451.      * If the image is wider than the width specified by $width,
  452.      * it will be scaled down to fit inside of it.
  453.      * If the image is smaller, nothing is done.
  454.      *
  455.      * @param integer $width 
  456.      * @return bool|PEAR_ErrorTRUE or PEAR_Error object on error
  457.      * @access public
  458.      */
  459.     function fitX($width)
  460.     {
  461.         return ($this->img_x <= $width? true : $this->scaleByX($width);
  462.     }
  463.  
  464.     /**
  465.      * Fits the image in the specified height
  466.      *
  467.      * If the image is taller than the height specified by $height,
  468.      * it will be scaled down to fit inside of it.
  469.      * If the image is smaller, nothing is done.
  470.      *
  471.      * @param integer $height 
  472.      * @return bool|PEAR_ErrorTRUE or PEAR_Error object on error
  473.      * @access public
  474.      */
  475.     function fitY($height)
  476.     {
  477.         return ($this->img_y <= $height? true : $this->scaleByY($height);
  478.     }
  479.  
  480.     /**
  481.      * Sets one options
  482.      *
  483.      * @param  string Name of option
  484.      * @param  mixed  Value of option
  485.      * @access public
  486.      * @see setOptions()
  487.      */
  488.     function setOption($name$value)
  489.     {
  490.         $this->_options[$name$value;
  491.     }
  492.  
  493.     /**
  494.      * Sets multiple options at once
  495.      *
  496.      * Associative array of options:
  497.      *  - quality     (Integer: 0: poor - 100: best)
  498.      *  - scaleMethod ('smooth', 'pixel')
  499.      *
  500.      * @param  array $options Array of options
  501.      * @access public
  502.      */
  503.     function setOptions($options)
  504.     {
  505.         $this->_options = array_merge($this->_options$options);
  506.     }
  507.  
  508.     /**
  509.      * Sets the image type (in lowercase letters), the image height and width.
  510.      *
  511.      * @return mixed TRUE or PEAR_error
  512.      * @access protected
  513.      * @see PHP_Compat::image_type_to_mime_type()
  514.      * @link http://php.net/getimagesize
  515.      */
  516.     function _get_image_details($image)
  517.     {
  518.         $data @getimagesize($image);
  519.         //  1 = GIF,   2 = JPG,  3 = PNG,  4 = SWF,  5 = PSD,  6 = BMP,
  520.         //  7 = TIFF (intel byte order),   8 = TIFF (motorola byte order),
  521.         //  9 = JPC,  10 = JP2, 11 = JPX, 12 = JB2, 13 = SWC, 14 = IFF,
  522.         // 15 = WBMP, 16 = XBM
  523.         if (!is_array($data)) {
  524.             return PEAR::raiseError("Cannot fetch image or images details."true);
  525.         }
  526.  
  527.         switch ($data[2]{
  528.             case IMAGETYPE_GIF:
  529.                 $type 'gif';
  530.                 break;
  531.             case IMAGETYPE_JPEG:
  532.                 $type 'jpeg';
  533.                 break;
  534.             case IMAGETYPE_PNG:
  535.                 $type 'png';
  536.                 break;
  537.             case IMAGETYPE_SWF:
  538.                 $type 'swf';
  539.                 break;
  540.             case IMAGETYPE_PSD:
  541.                 $type 'psd';
  542.                 break;
  543.             case IMAGETYPE_BMP:
  544.                 $type 'bmp';
  545.                 break;
  546.             case IMAGETYPE_TIFF_II:
  547.             case IMAGETYPE_TIFF_MM:
  548.                 $type 'tiff';
  549.                 break;
  550.             case IMAGETYPE_JPC:
  551.                 $type 'jpc';
  552.                 break;
  553.             case IMAGETYPE_JP2:
  554.                 $type 'jp2';
  555.                 break;
  556.             case IMAGETYPE_JPX:
  557.                 $type 'jpx';
  558.                 break;
  559.             case IMAGETYPE_JB2:
  560.                 $type 'jb2';
  561.                 break;
  562.             case IMAGETYPE_SWC:
  563.                 $type 'swc';
  564.                 break;
  565.             case IMAGETYPE_IFF:
  566.                 $type 'iff';
  567.                 break;
  568.             case IMAGETYPE_WBMP:
  569.                 $type 'wbmp';
  570.                 break;
  571.             case IMAGETYPE_XBM:
  572.                 $type 'xbm';
  573.                 break;
  574.             default:
  575.                 return PEAR::raiseError("Cannot recognize image format",
  576.                     IMAGE_TRANSFORM_ERROR_UNSUPPORTED);
  577.         }
  578.         $this->img_x = $this->new_x = $data[0];
  579.         $this->img_y = $this->new_y = $data[1];
  580.         $this->type  = $type;
  581.  
  582.         return true;
  583.     }
  584.  
  585.  
  586.     /**
  587.      * Returns the matching IMAGETYPE_* constant for a given image type
  588.      *
  589.      * @param  mixed $type String (GIF, JPG,...)
  590.      * @return mixed string or integer or input on error
  591.      * @access protected
  592.      * @see PHP_Compat::image_type_to_mime_type()
  593.      ***/
  594.     function _convert_image_type($type)
  595.     {
  596.         switch (strtolower($type)) {
  597.             case 'gif':
  598.                 return IMAGETYPE_GIF;
  599.             case 'jpeg':
  600.             case 'jpg':
  601.                 return IMAGETYPE_JPEG;
  602.             case 'png':
  603.                 return IMAGETYPE_PNG;
  604.             case 'swf':
  605.                 return IMAGETYPE_SWF;
  606.             case 'psd':
  607.                 return IMAGETYPE_PSD;
  608.             case 'bmp':
  609.                 return IMAGETYPE_BMP;
  610.             case 'tiff':
  611.                 return IMAGETYPE_TIFF_II;
  612.                 //IMAGETYPE_TIFF_MM;
  613.             case 'jpc':
  614.                 return IMAGETYPE_JPC;
  615.             case 'jp2':
  616.                 return IMAGETYPE_JP2;
  617.             case 'jpx':
  618.                 return IMAGETYPE_JPX;
  619.             case 'jb2':
  620.                 return IMAGETYPE_JB2;
  621.             case 'swc':
  622.                 return IMAGETYPE_SWC;
  623.             case 'iff':
  624.                 return IMAGETYPE_IFF;
  625.             case 'wbmp':
  626.                 return IMAGETYPE_WBMP;
  627.             case 'xbm':
  628.                 return IMAGETYPE_XBM;
  629.             default:
  630.                 return $type;
  631.         }
  632.  
  633.         return (isset($types[$t strtolower($type)])) $types[$t$type;
  634.     }
  635.  
  636.  
  637.     /**
  638.      * Parses input for number format and convert
  639.      *
  640.      * If either paramet