1<?php 2/* vim: set expandtab tabstop=4 shiftwidth=4: */ 3 4/** 5 * Cairo implementation for Image_Transform package 6 * 7 * PHP versions 4 and 5 8 * 9 * @category Image 10 * @package Image_Transform 11 * @subpackage Image_Transform_Driver_Cairowrapper 12 * @author Christian Weiske <cweiske@php.net> 13 * @copyright 2008 The PHP Group 14 * @license http://www.gnu.org/copyleft/lesser.html LGPL 15 * @version CVS: $Id: Cairowrapper.php 288112 2009-09-06 21:02:37Z cweiske $ 16 * @link http://pear.php.net/package/Image_Transform 17 */ 18require_once 'Image/Transform.php'; 19 20/** 21 * Cairo implementation for Image_Transform package using pecl's cairo_wrapper 22 * extension. 23 * 24 * Supports png files only. 25 * 26 * @category Image 27 * @package Image_Transform 28 * @subpackage Image_Transform_Driver_Cairowrapper 29 * @author Christian Weiske <cweiske@php.net> 30 * @copyright 2008 The PHP Group 31 * @license http://www.gnu.org/copyleft/lesser.html LGPL 32 * @version Release: @package_version@ 33 * @link http://pear.php.net/package/Image_Transform 34 */ 35class Image_Transform_Driver_Cairowrapper extends Image_Transform 36{ 37 var $surface = null; 38 39 /** 40 * Supported image types 41 * 42 * @var array 43 * @access protected 44 */ 45 var $_supported_image_types = array( 46 'png' => 'rw' 47 ); 48 49 /** 50 * Check settings 51 */ 52 function Image_Transform_Driver_Cairowrapper() 53 { 54 $this->__construct(); 55 } 56 57 58 59 /** 60 * Create object and check if cairo_wrapper is loaded 61 */ 62 function __construct() 63 { 64 if (!PEAR::loadExtension('cairo_wrapper')) { 65 $this->isError( 66 PEAR::raiseError( 67 'cairo_wrapper extension is not available.', 68 IMAGE_TRANSFORM_ERROR_UNSUPPORTED 69 ) 70 ); 71 } 72 } 73 74 75 76 /** 77 * Loads an image from file 78 * 79 * @param string $image filename 80 * 81 * @return bool|PEAR_Error TRUE or a PEAR_Error object on error 82 * 83 * @access public 84 */ 85 function load($image) 86 { 87 $this->free(); 88 89 $this->image = $image; 90 $result = $this->_get_image_details($image); 91 if (PEAR::isError($result)) { 92 return $result; 93 } 94 if (!$this->supportsType($this->type, 'r')) { 95 return PEAR::raiseError('Image type not supported for input', 96 IMAGE_TRANSFORM_ERROR_UNSUPPORTED); 97 } 98 99 $this->surface = cairo_image_surface_create_from_png($this->image); 100 if (cairo_surface_status($this->surface) != CAIRO_STATUS_SUCCESS) { 101 $this->surface = null; 102 return PEAR::raiseError('Error while loading image file.', 103 IMAGE_TRANSFORM_ERROR_IO); 104 } 105 106 return true; 107 }//function load(..) 108 109 110 111 /** 112 * Resize the image 113 * 114 * @param int $new_x New width 115 * @param int $new_y New height 116 * @param array $options Optional parameters 117 * 118 * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error 119 * 120 * @access protected 121 */ 122 function _resize($new_x, $new_y, $options = null) 123 { 124 if ($this->resized === true) { 125 return PEAR::raiseError( 126 'You have already resized the image without saving it.' 127 . ' Your previous resizing will be overwritten', 128 null, PEAR_ERROR_TRIGGER, E_USER_NOTICE 129 ); 130 } 131 132 if ($this->new_x == $new_x && $this->new_y == $new_y) { 133 return true; 134 } 135 136 $xFactor = $new_x / $this->img_x; 137 $yFactor = $new_y / $this->img_y; 138 139 $outputSurface = cairo_image_surface_create( 140 CAIRO_FORMAT_ARGB32, $new_x, $new_y 141 ); 142 $outputContext = cairo_create($outputSurface); 143 144 cairo_scale($outputContext, $xFactor, $yFactor); 145 146 cairo_set_source_surface($outputContext, $this->surface, 0, 0); 147 cairo_paint($outputContext); 148 149 cairo_destroy($outputContext); 150 151 cairo_surface_destroy($this->surface); 152 153 $this->surface = $outputSurface; 154 155 $this->new_x = $new_x; 156 $this->new_y = $new_y; 157 return true; 158 }//function _resize(..) 159 160 161 162 /** 163 * Saves the scaled image into a file. 164 * 165 * @param string $filename The filename to save to 166 * @param mixed $type ignored 167 * @param mixed $quality ignored 168 * 169 * @return bool|PEAR_Error TRUE on success or PEAR_Error object on error 170 * 171 * @access public 172 */ 173 function save($filename, $type = null, $quality = null) 174 { 175 cairo_surface_write_to_png($this->surface, $filename); 176 $this->free(); 177 return true; 178 }//function save(..) 179 180 181 182 /** 183 * Returns the surface of the image so it can be modified further 184 * 185 * @return resource 186 * 187 * @access public 188 */ 189 function getHandle() 190 { 191 return $this->surface; 192 }//function getHandle() 193 194 195 196 /** 197 * Frees cairo handles 198 * 199 * @return void 200 * 201 * @access public 202 */ 203 function free() 204 { 205 $this->resized = false; 206 if (is_resource($this->surface)) { 207 cairo_surface_destroy($this->surface); 208 } 209 $this->surface = null; 210 }//function free() 211 212 213 214 /** 215 * Mirrors the image vertically 216 * Uses an affine transformation matrix to flip the image. 217 * 218 * @return void 219 */ 220 function flip() 221 { 222 $outputSurface = cairo_image_surface_create( 223 CAIRO_FORMAT_ARGB32, $this->img_x, $this->img_y 224 ); 225 $outputContext = cairo_create($outputSurface); 226 // xx, yx, xy, yy, x0, y0 227 $matrix = cairo_matrix_create(1, 0, 0, -1, 0, $this->img_y); 228 229 cairo_set_matrix($outputContext, $matrix); 230 cairo_set_source_surface($outputContext, $this->surface, 0, 0); 231 cairo_paint($outputContext); 232 233 cairo_destroy($outputContext); 234 cairo_surface_destroy($this->surface); 235 236 $this->surface = $outputSurface; 237 }//function flip() 238 239 240 241 /** 242 * Mirrors the image horizontally. 243 * Uses an affine transformation matrix to mirror the image. 244 * 245 * 123 -> 321 246 * 247 * @return void 248 */ 249 function mirror() 250 { 251 $outputSurface = cairo_image_surface_create( 252 CAIRO_FORMAT_ARGB32, $this->img_x, $this->img_y 253 ); 254 $outputContext = cairo_create($outputSurface); 255 // xx, yx, xy, yy, x0, y0 256 $matrix = cairo_matrix_create(-1, 0, 0, 1, $this->img_x, 0); 257 258 cairo_set_matrix($outputContext, $matrix); 259 cairo_set_source_surface($outputContext, $this->surface, 0, 0); 260 cairo_paint($outputContext); 261 262 cairo_destroy($outputContext); 263 cairo_surface_destroy($this->surface); 264 265 $this->surface = $outputSurface; 266 }//function mirror() 267 268}//class Image_Transform_Driver_Cairowrapper extends Image_Transform 269?>