PageRenderTime 41ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

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