PageRenderTime 39ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Lib/mm/src/Media/Process/Adapter/Gd.php

https://github.com/bmcclure/CakePHP-Media-Plugin
PHP | 350 lines | 309 code | 24 blank | 17 comment | 24 complexity | 30103eb738e7e53f8eeeea2c247b6483 MD5 | raw file
  1. <?php
  2. /**
  3. * mm: the PHP media library
  4. *
  5. * Copyright (c) 2007-2012 David Persson
  6. *
  7. * Distributed under the terms of the MIT License.
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright 2007-2012 David Persson <nperson@gmx.de>
  11. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  12. * @link http://github.com/davidpersson/mm
  13. */
  14. require_once 'Media/Process/Adapter.php';
  15. require_once 'Mime/Type.php';
  16. /**
  17. * This media process adapter allows for interfacing with the native `gd` pecl extension.
  18. *
  19. * @link http://php.net/gd
  20. */
  21. class Media_Process_Adapter_Gd extends Media_Process_Adapter {
  22. protected $_object;
  23. protected $_formatMap = array(
  24. 'image/jpeg' => 'jpeg',
  25. 'image/gif' => 'gif',
  26. 'image/png' => 'png',
  27. 'image/gd' => 'gd',
  28. 'image/vnd.wap.wbmp' => 'wbmp',
  29. 'image/xbm' => 'xbm',
  30. );
  31. protected $_format;
  32. protected $_compression;
  33. protected $_pngFilter;
  34. public function __construct($handle) {
  35. $mimeType = Mime_Type::guessType($handle);
  36. if (!isset($this->_formatMap[$mimeType])) {
  37. throw new OutOfBoundsException("Could not map MIME-type `{$mimeType}` to format.");
  38. }
  39. $this->_format = $this->_formatMap[$mimeType];
  40. $this->_object = imageCreateFromString(stream_get_contents($handle));
  41. if (!$this->_isResource($this->_object)) {
  42. throw new Exception("Was not able to create image from handle.");
  43. }
  44. if (imageIsTrueColor($this->_object)) {
  45. imageAlphaBlending($this->_object, false);
  46. imageSaveAlpha($this->_object, true);
  47. }
  48. }
  49. public function __destruct() {
  50. if ($this->_isResource($this->_object)) {
  51. imageDestroy($this->_object);
  52. }
  53. }
  54. public function store($handle) {
  55. $args = array($this->_object);
  56. switch ($this->_format) {
  57. case 'jpeg':
  58. if (isset($this->_compression)) {
  59. if (count($args) == 1) {
  60. $args[] = null;
  61. }
  62. $args[] = $this->_compression;
  63. }
  64. break;
  65. case 'png':
  66. if (isset($this->_compression)) {
  67. if (count($args) == 1) {
  68. $args[] = null;
  69. }
  70. $args[] = $this->_compression;
  71. if (isset($this->_pngFilter)) {
  72. $args[] = $this->_pngFilter;
  73. }
  74. }
  75. break;
  76. }
  77. ob_start();
  78. call_user_func_array('image' . $this->_format, $args);
  79. $blob = ob_get_clean();
  80. rewind($handle);
  81. return fwrite($handle, $blob);
  82. }
  83. public function convert($mimeType) {
  84. if (Mime_Type::guessName($mimeType) != 'image') {
  85. return true;
  86. }
  87. if (isset($this->_formatMap[$mimeType])) {
  88. return $this->_format = $this->_formatMap[$mimeType];
  89. }
  90. return false;
  91. }
  92. public function passthru($key, $value) {
  93. throw new Exception("The adapter has no passthru support.");
  94. }
  95. public function compress($value) {
  96. switch ($this->_format) {
  97. case 'jpeg':
  98. $this->_compression = (integer) (100 - ($value * 10));
  99. break;
  100. case 'png':
  101. if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
  102. $this->_compression = (integer) $value;
  103. }
  104. if (version_compare(PHP_VERSION, '5.1.3', '>=')) {
  105. $filter = ($value * 10) % 10;
  106. $map = array(
  107. 0 => PNG_FILTER_NONE,
  108. 1 => PNG_FILTER_SUB,
  109. 2 => PNG_FILTER_UP,
  110. 3 => PNG_FILTER_AVG,
  111. 4 => PNG_FILTER_PAETH,
  112. );
  113. if (array_key_exists($filter, $map)) {
  114. $this->_pngFilter = $map[$filter];
  115. } elseif ($filter == 5) {
  116. if (intval($value) <= 5 && imageIsTrueColor($this->_object)) {
  117. $this->_pngFilter = PNG_ALL_FILTERS;
  118. } else {
  119. $this->_pngFilter = PNG_NO_FILTER;
  120. }
  121. } else {
  122. $this->_pngFilter = PNG_ALL_FILTERS;
  123. }
  124. }
  125. break;
  126. }
  127. return true;
  128. }
  129. public function profile($type, $data = null) {
  130. throw new Exception("The adapter doesn't support the `profile` action.");
  131. }
  132. public function strip($type) {
  133. throw new Exception("The adapter doesn't support the `strip` action.");
  134. }
  135. public function depth($value) {
  136. throw new Exception("The adapter doesn't support the `depth` action.");
  137. }
  138. public function interlace($value) {
  139. if (in_array($this->_format, array('jpeg', 'png', 'gif'))) {
  140. imageInterlace($this->_object, $value ? 1 : 0);
  141. return true;
  142. }
  143. return false;
  144. }
  145. public function crop($left, $top, $width, $height) {
  146. $left = (integer) $left;
  147. $top = (integer) $top;
  148. $width = (integer) $width;
  149. $height = (integer) $height;
  150. $image = imageCreateTrueColor($width, $height);
  151. $this->_adjustTransparency($this->_object, $image);
  152. if ($this->_isTransparent($this->_object)) {
  153. imageCopyResized(
  154. $image,
  155. $this->_object,
  156. 0, 0,
  157. $left, $top,
  158. $width, $height,
  159. $width, $height
  160. );
  161. } else {
  162. imageCopyResampled(
  163. $image,
  164. $this->_object,
  165. 0, 0,
  166. $left, $top,
  167. $width, $height,
  168. $width, $height
  169. );
  170. }
  171. if ($this->_isResource($image)) {
  172. $this->_object = $image;
  173. return true;
  174. }
  175. return false;
  176. }
  177. public function resize($width, $height) {
  178. $width = (integer) $width;
  179. $height = (integer) $height;
  180. $image = imageCreateTrueColor($width, $height);
  181. $this->_adjustTransparency($this->_object, $image);
  182. if ($this->_isTransparent($this->_object)) {
  183. imageCopyResized(
  184. $image,
  185. $this->_object,
  186. 0, 0,
  187. 0, 0,
  188. $width, $height,
  189. $this->width(), $this->height()
  190. );
  191. } else {
  192. imageCopyResampled(
  193. $image,
  194. $this->_object,
  195. 0, 0,
  196. 0, 0,
  197. $width, $height,
  198. $this->width(), $this->height()
  199. );
  200. }
  201. if ($this->_isResource($image)) {
  202. $this->_object = $image;
  203. return true;
  204. }
  205. return false;
  206. }
  207. public function fitInsideWhite($width, $height, $new_width, $new_height){
  208. $width = (integer) $width;
  209. $height = (integer) $height;
  210. $new_width = (integer) $new_width;
  211. $new_height = (integer) $new_height;
  212. $x = $y = 0;
  213. if($new_height > $this->height())
  214. $x = floor(($width - $new_width) / 2);
  215. else
  216. $y = floor(($height - $new_height) / 2);
  217. $image = imageCreateTrueColor($width, $height);
  218. imageFill($image, 0, 0, imageColorAllocate($image, 255, 255, 255));
  219. imageCopyResampled(
  220. $image,
  221. $this->_object,
  222. $x, $y,
  223. 0, 0,
  224. $new_width, $new_height,
  225. $this->width(), $this->height()
  226. );
  227. if ($this->_isResource($image)) {
  228. $this->_object = $image;
  229. return true;
  230. }
  231. return false;
  232. }
  233. public function cropAndResize($cropLeft, $cropTop, $cropWidth, $cropHeight, $resizeWidth, $resizeHeight) {
  234. $cropLeft = (integer) $cropLeft;
  235. $cropTop = (integer) $cropTop;
  236. $cropWidth = (integer) $cropWidth;
  237. $cropHeight = (integer) $cropHeight;
  238. $resizeWidth = (integer) $resizeWidth;
  239. $resizeHeight = (integer) $resizeHeight;
  240. $image = imageCreateTrueColor($resizeWidth, $resizeHeight);
  241. $this->_adjustTransparency($this->_object, $image);
  242. if ($this->_isTransparent($this->_object)) {
  243. imageCopyResized(
  244. $image,
  245. $this->_object,
  246. 0, 0,
  247. $cropLeft, $cropTop,
  248. $resizeWidth, $resizeHeight,
  249. $cropWidth, $cropHeight
  250. );
  251. } else {
  252. imageCopyResampled(
  253. $image,
  254. $this->_object,
  255. 0, 0,
  256. $cropLeft, $cropTop,
  257. $resizeWidth, $resizeHeight,
  258. $cropWidth, $cropHeight
  259. );
  260. }
  261. if ($this->_isResource($image)) {
  262. $this->_object = $image;
  263. return true;
  264. }
  265. return false;
  266. }
  267. public function width() {
  268. return imageSX($this->_object);
  269. }
  270. public function height() {
  271. return imageSY($this->_object);
  272. }
  273. protected function _isResource($image) {
  274. return is_resource($image) && get_resource_type($image) == 'gd';
  275. }
  276. protected function _isTransparent($image) {
  277. return imageColorTransparent($image) >= 0;
  278. }
  279. protected function _adjustTransparency(&$source, &$target) {
  280. if ($this->_isTransparent($source)) {
  281. $rgba = imageColorsForIndex($source, imageColorTransparent($source));
  282. $color = imageColorAllocate($target, $rgba['red'], $rgba['green'], $rgba['blue']);
  283. imageColorTransparent($target, $color);
  284. imageFill($target, 0, 0, $color);
  285. } else {
  286. if ($this->_format == 'png') {
  287. imageAlphaBlending($target, false);
  288. imageSaveAlpha($target, true);
  289. } elseif ($this->_format != 'gif') {
  290. $white = imageColorAllocate($target, 255, 255, 255);
  291. imageFill($target, 0, 0 , $white);
  292. }
  293. }
  294. }
  295. protected function _rgb2array($rgb) {
  296. return array(
  297. base_convert(substr($rgb, 0, 2), 16, 10),
  298. base_convert(substr($rgb, 2, 2), 16, 10),
  299. base_convert(substr($rgb, 4, 2), 16, 10),
  300. );
  301. }
  302. }
  303. ?>