PageRenderTime 84ms CodeModel.GetById 40ms app.highlight 13ms RepoModel.GetById 27ms app.codeStats 0ms

/plugins/sfImageTransformPlugin/lib/adapters/sfImageTransformGDAdapter.class.php

https://bitbucket.org/Kudlaty/360kdw
PHP | 502 lines | 256 code | 82 blank | 164 comment | 29 complexity | e1247aedae803083ceeb015d558f1d54 MD5 | raw file
  1<?php
  2/*
  3 * This file is part of the sfImageTransform package.
  4 * (c) 2007 Stuart Lowes <stuart.lowes@gmail.com>
  5 *
  6 * For the full copyright and license information, please view the LICENSE
  7 * file that was distributed with this source code.
  8 */
  9
 10/**
 11 *
 12 * sfImageTransformGDAdapter class.
 13 *
 14 * GD support for sfImageTransform.
 15 *
 16 * @package sfImageTransform
 17 * @subpackage adapters
 18 * @author Stuart Lowes <stuart.lowes@gmail.com>
 19 * @version SVN: $Id$
 20 */
 21class sfImageTransformGDAdapter extends sfImageTransformAdapterAbstract
 22{
 23  /**
 24   * The image resource.
 25   * @access protected
 26   * @var resource
 27  */
 28  protected $holder;
 29
 30  /*
 31   * Supported MIME types for the sfImageGDAdapter
 32   * and their associated file extensions
 33   * @var array
 34   */
 35  protected $types = array(
 36    'image/jpeg' => array('jpeg','jpg'),
 37    'image/gif' => array('gif'),
 38    'image/png' => array('png')
 39  );
 40
 41  /*
 42   * List of GD functions used to load specific image types
 43   * @var array
 44   */
 45  protected $loaders = array(
 46    'image/jpeg' => 'imagecreatefromjpeg',
 47    'image/jpg' => 'imagecreatefromjpeg',
 48    'image/gif' => 'imagecreatefromgif',
 49    'image/png' => 'imagecreatefrompng'
 50  );
 51
 52  /*
 53   * List of GD functions used to create specific image types
 54   * @var array
 55   */
 56  protected $creators = array(
 57    'image/jpeg' => 'imagejpeg',
 58    'image/jpg' => 'imagejpeg',
 59    'image/gif' => 'imagegif',
 60    'image/png' => 'imagepng'
 61  );
 62
 63  /**
 64   * Initialize the object. Check for GD extension. An exception is thrown if not installed
 65   *
 66   * @throws sfImageTransformException
 67   */
 68  public function __construct()
 69  {
 70    // Check that the GD extension is installed and configured
 71    if (!extension_loaded('gd'))
 72    {
 73      throw new sfImageTransformException('The image processing library GD is not enabled. See PHP Manual for installation instructions.');
 74    }
 75  }
 76
 77  /**
 78   * Tidy up the image resources
 79   */
 80  public function __destruct()
 81  {
 82    if ($this->hasHolder())
 83    {
 84      imagedestroy($this->getHolder());
 85    }
 86  }
 87
 88  /**
 89   * Create a new empty (1 x 1 px) gd true colour image
 90   * @param integer Width
 91   * @param integer Height
 92   */
 93  public function create($x=1, $y=1)
 94  {
 95    $this->setHolder(imagecreatetruecolor($x,$y));
 96    imagefill($this->holder,0,0,imagecolorallocate($this->getHolder(), 255, 255, 255));
 97  }
 98
 99  /**
100   * Load and sets the resource from a existing file
101   * @param string
102   * @return boolean
103   *
104   * @throws sfImageTransformException
105   */
106  public function load($filename, $mime)
107  {
108    if (array_key_exists($mime,$this->loaders))
109    {
110      $this->holder = $this->loaders[$mime]($filename);
111      $this->mime_type = $mime;
112      $this->setFilename($filename);
113
114      return true;
115    }
116
117    else
118    {
119        throw new sfImageTransformException(sprintf('Cannot load file %s as %s is an unsupported file type.', $filename, $mime));
120    }
121  }
122
123  /**
124   * Loads an image from a string
125   * @param string String image
126   * @return boolean
127   */
128  public function loadString($string)
129  {
130    $resource = imagecreatefromstring($string);
131
132    if (is_resource($resource) && 'gd' === get_resource_type($resource))
133    {
134      $this->setHolder($resource);
135
136      return true;
137    }
138
139    return false;
140  }
141
142  /**
143   * Get the image as string
144   *
145   * @return string
146   */
147  public function __toString()
148  {
149    ob_start();
150    $this->__output(false);
151
152    return ob_get_clean();
153  }
154
155  /**
156   * Save the image to disk
157   *
158   * @return boolean
159   */
160  public function save()
161  {
162    $this->__output(true);
163    
164    return true; 
165  }
166
167  /**
168   * Save the image to disk
169   *
170   * @param string Filename
171   * @param string MIME type
172   * @return boolean
173   */
174  public function saveAs($filename, $mime='')
175  {
176    if ('' !== $mime)
177    {
178      if (!$this->setMimeType($mime))
179      {
180        throw new sfImageTransformException(sprintf('Cannot convert as %s is an unsupported type' ,$mime));
181      }
182    }
183
184    $this->setFilename($filename);
185
186    return $this->__output(true, $filename);
187  }
188
189  /**
190   * Returns a copy of the adapter object
191   *
192   * @return sfImage
193   */
194  public function copy()
195  {
196    $copyObj = clone $this;
197
198    $copy = $this->getTransparentImage($this->getWidth(), $this->getHeight());
199    imagecopy($copy, $this->getHolder(), 0, 0, 0, 0, $this->getWidth(), $this->getHeight());
200
201    $copyObj->setHolder($copy);
202
203    return $copyObj;
204  }
205
206  /**
207   * Gets the pixel width of the image
208   *
209   * @return integer
210   */
211  public function getWidth()
212  {
213    if ($this->hasHolder())
214    {
215      return imagesx($this->getHolder());
216    }
217
218    return 0;
219  }
220
221  /**
222   * Gets the pixel height of the image
223   *
224   * @return integer
225   */
226  public function getHeight()
227  {
228    if ($this->hasHolder())
229    {
230      return imagesy($this->getHolder());
231    }
232
233    return 0;
234  }
235
236  /**
237   * Sets the image resource holder
238   * @param GD resource object
239   * @return boolean
240   *
241   */
242  public function setHolder($resource)
243  {
244
245    if (is_resource($resource) && 'gd' === get_resource_type($resource))
246    {
247
248      $this->holder = $resource;
249      
250      return true;
251    }
252
253    return false;
254  }
255
256  /**
257   * Returns the image resource
258   * @return resource
259   *
260   */
261  public function getHolder()
262  {
263    if ($this->hasHolder())
264    {
265      return $this->holder;
266    }
267
268    return false;
269  }
270
271  /**
272   * Returns whether there is a valid GD image resource
273   * @return boolean
274   *
275   */
276  public function hasHolder()
277  {
278    if (is_resource($this->holder) && 'gd' === get_resource_type($this->holder))
279    {
280      return true;
281    }
282
283    return false;
284  }
285
286 /**
287   * Returns image MIME type
288   * @return boolean
289   *
290   */
291  public function getMIMEType()
292  {
293    return $this->mime_type;
294  }
295
296 /**
297   * Returns image MIME type
298   * @param string valid MIME Type
299   * @return boolean
300   *
301   */
302  public function setMIMEType($mime)
303  {
304    if (array_key_exists($mime,$this->loaders))
305    {
306      $this->mime_type = $mime;
307      return true;
308    }
309
310    return false;
311  }
312
313 /**
314   * Returns image MIME type
315   * @return boolean
316   *
317   */
318  public function getMIMETypeFromFilename($filename)
319  {
320
321    $path = pathinfo($filename);
322
323    foreach($this->types as $type => $extensions)
324    {
325      if (in_array($path['extension'], $extensions))
326      {
327        return $type;
328      }
329
330    }
331
332    return false;
333  }
334
335 /**
336   * Returns the name of the adapter
337   * @return string
338   *
339   */
340  public function getAdapterName()
341  {
342    return 'GD';
343  }
344
345  /**
346   * Returns the image color for a hex value (format #XXXXXX).
347   *
348   * @param resource image resource
349   * @param string full hex value of the color or GD constant
350   * @return integer
351   */
352  public function getColorByHex($image, $color)
353  {
354
355    if (preg_match('/#[\d\w]{6}/',$color))
356    {
357      $rgb = sscanf($color, '#%2x%2x%2x');
358      $color = imagecolorallocate($image, $rgb[0], $rgb[1], $rgb[2]);
359
360      return $color;
361    }
362
363    return $color;
364  }
365
366 /**
367   * Returns image in current format and optionally writes image to disk
368   * @return resource
369   *
370   * @throws sfImageTransformException
371   */
372  protected function __output($to_file=false, $filename='')
373  {
374    $file = null;
375
376    // Are we saving to file, if so get the filename to save to
377    if ($to_file)
378    {
379      $file = $filename;
380      if ('' === $file)
381      {
382        $file = $this->getFilename();
383      }
384    }
385
386    $mime = $this->getMimeType();
387
388    if (array_key_exists($mime,$this->creators))
389    {
390
391      switch ($mime)
392      {
393
394        case 'image/jpeg':
395        case 'image/jpg':
396          if (is_null($this->quality))
397          {
398            $this->quality = 75;
399          }
400          $output = $this->creators[$mime]($this->holder,$file,$this->getImageSpecificQuality($this->quality, $mime));
401          break;
402
403        case 'image/png':
404          imagesavealpha($this->holder, true);
405          $output = $this->creators[$mime]($this->holder,$file,$this->getImageSpecificQuality($this->quality, $mime), null);
406          break;
407
408        case 'image/gif':
409
410          if (!is_null($file))
411          {
412            $output = $this->creators[$mime]($this->holder,$file);
413          }
414          else
415          {
416            $output = $this->creators[$mime]($this->holder);
417          }
418          break;
419
420        default:
421          throw new sfImageTransformException(sprintf('Cannot convert as %s is an unsupported type' ,$mime));
422      }
423    }
424    else
425    {
426      throw new sfImageTransformException(sprintf('Cannot convert as %s is an unsupported type' ,$mime));
427    }
428
429    return $output;
430  }
431
432  protected function getImageSpecificQuality($quality, $mime)
433  {
434    // Range is from 0-100
435
436    if ('image/png' === $mime)
437    {
438
439      return 9 - round($quality * (9/100));
440    }
441
442    return $quality;
443  }
444
445 /**
446   * Helper method. Returns a transparent image resource of the specified size
447   * @param integer width
448   * @param integer height
449   * @return resource image
450   *
451   * @throws sfImageTransformException
452   */
453  public function getTransparentImage($w, $h)
454  {
455
456    $resource = $this->getHolder();
457
458    $dest_resource = imagecreatetruecolor((int)$w, (int)$h);
459
460    // Preserve alpha transparency
461    if (in_array($this->getMIMEType(), array('image/gif','image/png')))
462    {
463      $index = imagecolortransparent($resource);
464
465      // Handle transparency
466      if ($index >= 0)
467      {
468
469        // Grab the current images transparent color
470        $index_color = imagecolorsforindex($resource, $index);
471
472        // Set the transparent color for the resized version of the image
473        $index = imagecolorallocate($dest_resource, $index_color['red'], $index_color['green'], $index_color['blue']);
474
475        // Fill the entire image with our transparent color
476        imagefill($dest_resource, 0, 0, $index);
477
478        // Set the filled background color to be transparent
479        imagecolortransparent($dest_resource, $index);    
480      }
481      else if ($this->getMIMEType() == 'image/png') // Always make a transparent background color for PNGs that don't have one allocated already
482      {
483
484        // Disabled blending
485        imagealphablending($dest_resource, false);
486
487        // Grab our alpha tranparency color
488        $color = imagecolorallocatealpha($dest_resource, 0, 0, 0, 127);
489
490        // Fill the entire image with our transparent color
491        imagefill($dest_resource, 0, 0, $color);
492
493        // Re-enable transparency blending
494        imagesavealpha($dest_resource, true);
495      }
496    }
497
498    return $dest_resource;
499
500  }
501
502}