PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/system/core/image.php

https://gitlab.com/Ltaimao/wecenter
PHP | 437 lines | 339 code | 83 blank | 15 comment | 55 complexity | 938e09d7a2fc59664cb62b5c91d2c960 MD5 | raw file
  1. <?php
  2. /*
  3. +--------------------------------------------------------------------------
  4. | WeCenter [#RELEASE_VERSION#]
  5. | ========================================
  6. | by WeCenter Software
  7. | © 2011 - 2014 WeCenter. All Rights Reserved
  8. | http://www.wecenter.com
  9. | ========================================
  10. | Support: WeCenter@qq.com
  11. |
  12. +---------------------------------------------------------------------------
  13. */
  14. define(IMAGE_CORE_OP_TO_FILE, 1); // Output to file
  15. define(IMAGE_CORE_OP_OUTPUT, 2); // Output to browser
  16. define(IMAGE_CORE_SC_NOT_KEEP_SCALE, 4); // Free scale
  17. define(IMAGE_CORE_SC_BEST_RESIZE_WIDTH, 8); // Scale to width
  18. define(IMAGE_CORE_SC_BEST_RESIZE_HEIGHT, 16); // Scale to height
  19. define(IMAGE_CORE_CM_DEFAULT, 0); // Clipping method: default
  20. define(IMAGE_CORE_CM_LEFT_OR_TOP, 1); // Clipping method: left or top
  21. define(IMAGE_CORE_CM_MIDDLE, 2); // Clipping method: middle
  22. define(IMAGE_CORE_CM_RIGHT_OR_BOTTOM, 3); // Clipping method: right or bottom
  23. class core_image
  24. {
  25. var $image_library = 'gd';
  26. var $source_image;
  27. var $new_image;
  28. var $width;
  29. var $height;
  30. var $quality = 90;
  31. var $option = IMAGE_CORE_OP_TO_FILE;
  32. var $scale;
  33. // clipping method 0: default 1: left or top 2: middle 3: right or bottom
  34. var $clipping = IMAGE_CORE_CM_MIDDLE;
  35. var $start_x = 0; // start X axis (pixel)
  36. var $start_y = 0; // start Y axis (pixel)
  37. private $image_type = array(
  38. 1 => 'gif',
  39. 2 => 'jpeg',
  40. 3 => 'png'
  41. );
  42. private $image_type_index = array(
  43. 'gif' => 1,
  44. 'jpg' => 2,
  45. 'jpeg' => 2,
  46. 'jpe' => 2,
  47. 'png' => 3
  48. );
  49. private $image_info;
  50. private $image_ext;
  51. public function initialize($config = array())
  52. {
  53. if (!defined('IN_SAE'))
  54. {
  55. if (class_exists('Imagick', false))
  56. {
  57. $this->image_library = 'imagemagick';
  58. }
  59. }
  60. if (sizeof($config) > 0)
  61. {
  62. foreach ($config AS $key => $value)
  63. {
  64. $this->$key = $value;
  65. }
  66. }
  67. return $this;
  68. }
  69. public function resize()
  70. {
  71. if (!file_exists($this->source_image))
  72. {
  73. throw new Zend_Exception('Source file not exists: ' . $this->source_image);
  74. }
  75. $this->image_info = @getimagesize($this->source_image);
  76. switch ($this->image_info[2])
  77. {
  78. default:
  79. throw new Zend_Exception('Can\'t detect output image\'s type: ' . $this->source_image);
  80. break;
  81. case 1:
  82. $this->image_ext = 'gif';
  83. break;
  84. case 2:
  85. $this->image_ext = 'jpg';
  86. break;
  87. case 3:
  88. $this->image_ext = 'png';
  89. break;
  90. }
  91. if ($this->image_library == 'imagemagick')
  92. {
  93. return $this->imageProcessImageMagick();
  94. }
  95. else
  96. {
  97. return $this->imageProcessGD();
  98. }
  99. }
  100. private function imageProcessImageMagick()
  101. {
  102. $this->source_image_w = $this->image_info[0];
  103. $this->source_image_h = $this->image_info[1];
  104. $this->source_image_x = 0;
  105. $this->source_image_y = 0;
  106. $dst_x = 0;
  107. $dst_y = 0;
  108. if ($this->clipping != IMAGE_CORE_CM_DEFAULT)
  109. {
  110. // clipping method 1: left or top 2: middle 3: right or bottom
  111. $this->source_image_w -= $this->start_x;
  112. $this->source_image_h -= $this->start_y;
  113. if ($this->source_image_w * $this->height > $this->source_image_h * $this->width)
  114. {
  115. $match_w = round($this->width * $this->source_image_h / $this->height);
  116. $match_h = $this->source_image_h;
  117. }
  118. else
  119. {
  120. $match_h = round($this->height * $this->source_image_w / $this->width);
  121. $match_w = $this->source_image_w;
  122. }
  123. switch ($this->clipping)
  124. {
  125. case IMAGE_CORE_CM_LEFT_OR_TOP:
  126. $this->source_image_x = 0;
  127. $this->source_image_y = 0;
  128. break;
  129. case IMAGE_CORE_CM_MIDDLE:
  130. $this->source_image_x = round(($this->source_image_w - $match_w) / 2);
  131. $this->source_image_y = round(($this->source_image_h - $match_h) / 2);
  132. break;
  133. case IMAGE_CORE_CM_RIGHT_OR_BOTTOM:
  134. $this->source_image_x = $this->source_image_w - $match_w;
  135. $this->source_image_y = $this->source_image_h - $match_h;
  136. break;
  137. }
  138. $this->source_image_w = $match_w;
  139. $this->source_image_h = $match_h;
  140. $this->source_image_x += $this->start_x;
  141. $this->source_image_y += $this->start_y;
  142. }
  143. $resize_height = $this->height;
  144. $resize_width = $this->width;
  145. if ($this->scale != IMAGE_CORE_SC_NOT_KEEP_SCALE)
  146. {
  147. if ($this->scale == IMAGE_CORE_SC_BEST_RESIZE_WIDTH)
  148. {
  149. $resize_height = round($this->width * $this->source_image_h / $this->source_image_w);
  150. $resize_width = $this->width;
  151. }
  152. else if ($this->scale == IMAGE_CORE_SC_BEST_RESIZE_HEIGHT)
  153. {
  154. $resize_width = round($this->height * $this->source_image_w / $this->source_image_h);
  155. $resize_height = $this->height;
  156. }
  157. }
  158. $im = new Imagick();
  159. $im->readimageblob(file_get_contents($this->source_image));
  160. $im->setCompressionQuality($this->quality);
  161. if ($this->source_image_x OR $this->source_image_y)
  162. {
  163. $im->cropImage($this->source_image_w, $this->source_image_h, $this->source_image_x, $this->source_image_y);
  164. }
  165. $im->thumbnailImage($resize_width, $resize_height, true);
  166. if ($this->option == IMAGE_CORE_OP_TO_FILE AND $this->new_image)
  167. {
  168. file_put_contents($this->new_image, $im->getimageblob());
  169. }
  170. else if ($this->option == IMAGE_CORE_OP_OUTPUT)
  171. {
  172. $output = $im->getimageblob();
  173. $outputtype = $im->getFormat();
  174. header("Content-type: $outputtype");
  175. echo $output;
  176. die;
  177. }
  178. return TRUE;
  179. }
  180. private function imageProcessGD()
  181. {
  182. $func_output = 'image' . $this->image_type[$this->image_type_index[$this->image_ext]];
  183. if (!function_exists($func_output))
  184. {
  185. throw new Zend_Exception('Function not exists for output: ' . $func_output);
  186. }
  187. $func_create = 'imagecreatefrom' . $this->image_type[$this->image_info[2]];
  188. if (!function_exists($func_create))
  189. {
  190. throw new Zend_Exception('Function not exists for output: ' . $func_create);
  191. }
  192. $im = $func_create($this->source_image);
  193. $this->source_image_w = $this->image_info[0];
  194. $this->source_image_h = $this->image_info[1];
  195. $this->source_image_x = 0;
  196. $this->source_image_y = 0;
  197. $dst_x = 0;
  198. $dst_y = 0;
  199. if ($this->scale == IMAGE_CORE_SC_BEST_RESIZE_WIDTH)
  200. {
  201. $this->height = round($this->width * $this->source_image_h / $this->source_image_w);
  202. }
  203. if ($this->scale & IMAGE_CORE_SC_BEST_RESIZE_HEIGHT)
  204. {
  205. $this->width = round($this->height * $this->source_image_w / $this->source_image_h);
  206. }
  207. $fdst_w = $this->width;
  208. $fdst_h = $this->height;
  209. if ($this->clipping != IMAGE_CORE_CM_DEFAULT)
  210. {
  211. // clipping method 1: left or top 2: middle 3: right or bottom
  212. $this->source_image_w -= $this->start_x;
  213. $this->source_image_h -= $this->start_y;
  214. if ($this->source_image_w * $this->height > $this->source_image_h * $this->width)
  215. {
  216. $match_w = round($this->width * $this->source_image_h / $this->height);
  217. $match_h = $this->source_image_h;
  218. }
  219. else
  220. {
  221. $match_h = round($this->height * $this->source_image_w / $this->width);
  222. $match_w = $this->source_image_w;
  223. }
  224. switch ($this->clipping)
  225. {
  226. case IMAGE_CORE_CM_LEFT_OR_TOP:
  227. $this->source_image_x = 0;
  228. $this->source_image_y = 0;
  229. break;
  230. case IMAGE_CORE_CM_MIDDLE:
  231. $this->source_image_x = round(($this->source_image_w - $match_w) / 2);
  232. $this->source_image_y = round(($this->source_image_h - $match_h) / 2);
  233. break;
  234. case IMAGE_CORE_CM_RIGHT_OR_BOTTOM:
  235. $this->source_image_x = $this->source_image_w - $match_w;
  236. $this->source_image_y = $this->source_image_h - $match_h;
  237. break;
  238. }
  239. $this->source_image_w = $match_w;
  240. $this->source_image_h = $match_h;
  241. $this->source_image_x += $this->start_x;
  242. $this->source_image_y += $this->start_y;
  243. }
  244. else if ($this->scale != IMAGE_CORE_SC_NOT_KEEP_SCALE)
  245. {
  246. if ($this->source_image_w * $this->height > $this->source_image_h * $this->width)
  247. {
  248. $fdst_h = round($this->source_image_h * $this->width / $this->source_image_w);
  249. $dst_y = floor(($this->height - $fdst_h) / 2);
  250. $fdst_w = $this->width;
  251. }
  252. else
  253. {
  254. $fdst_w = round($this->source_image_w * $this->height / $this->source_image_h);
  255. $dst_x = floor(($this->width - $fdst_w) / 2);
  256. $fdst_h = $this->height;
  257. }
  258. if ($dst_x < 0)
  259. {
  260. $dst_x = 0;
  261. $dst_y = 0;
  262. }
  263. if ($dst_x > ($this->width / 2))
  264. {
  265. $dst_x = floor($this->width / 2);
  266. }
  267. if ($dst_y > ($this->height / 2))
  268. {
  269. $dst_y = floor($this->height / 2);
  270. }
  271. }
  272. if (function_exists('imagecopyresampled') AND function_exists('imagecreatetruecolor')) // GD Version Check
  273. {
  274. $func_create = 'imagecreatetruecolor';
  275. $func_resize = 'imagecopyresampled';
  276. }
  277. else
  278. {
  279. $func_create = 'imagecreate';
  280. $func_resize = 'imagecopyresized';
  281. }
  282. $dst_img = $func_create($this->width, $this->height);
  283. if ($this->image_ext == 'png') // png we can actually preserve transparency
  284. {
  285. imagealphablending($dst_img, FALSE);
  286. imagesavealpha($dst_img, TRUE);
  287. }
  288. $func_resize($dst_img, $im, $dst_x, $dst_y, $this->source_image_x, $this->source_image_y, $fdst_w, $fdst_h, $this->source_image_w, $this->source_image_h);
  289. if ($this->option == IMAGE_CORE_OP_TO_FILE AND $this->new_image)
  290. {
  291. if (file_exists($this->new_image))
  292. {
  293. @unlink($this->new_image);
  294. }
  295. if (defined('IN_SAE'))
  296. {
  297. $this->new_image = str_replace(get_setting('upload_dir'), '', $this->new_image);
  298. $sae_storage = new SaeStorage();
  299. }
  300. switch ($this->image_type_index[$this->image_ext])
  301. {
  302. case 1:
  303. case 3:
  304. if (defined('IN_SAE'))
  305. {
  306. ob_start();
  307. $func_output($dst_img);
  308. $sae_storage->write('uploads', $this->new_image, ob_get_contents());
  309. ob_end_clean();
  310. }
  311. else
  312. {
  313. $func_output($dst_img, $this->new_image);
  314. }
  315. break;
  316. case 2: // JPEG
  317. if (defined('IN_SAE'))
  318. {
  319. ob_start();
  320. $func_output($dst_img, null, $this->quality);
  321. $sae_storage->write('uploads', $this->new_image, ob_get_contents());
  322. ob_end_clean();
  323. }
  324. else
  325. {
  326. $func_output($dst_img, $this->new_image, $this->quality);
  327. }
  328. break;
  329. }
  330. }
  331. else if ($this->option == IMAGE_CORE_OP_OUTPUT)
  332. {
  333. if (function_exists("headers_sent") AND headers_sent())
  334. {
  335. throw new Zend_Exception('HTTP already sent, can\'t output image to browser.');
  336. }
  337. header('Content-Type: image/' . $this->image_type[$this->image_type_index[$this->image_ext]]);
  338. switch ($this->image_type_index[$this->image_ext])
  339. {
  340. case 1:
  341. case 3:
  342. $func_output($dst_img);
  343. break;
  344. case 2: // JPEG
  345. $func_output($dst_img, '', $this->quality);
  346. break;
  347. }
  348. die;
  349. }
  350. @imagedestroy($im);
  351. @imagedestroy($dst_img);
  352. return TRUE;
  353. }
  354. }