PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/program/include/rcube_image.php

https://github.com/netconstructor/roundcubemail
PHP | 268 lines | 165 code | 40 blank | 63 comment | 50 complexity | c803f670220e59acf359922dd1cba03a MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1
  1. <?php
  2. /*
  3. +-----------------------------------------------------------------------+
  4. | program/include/rcube_image.php |
  5. | |
  6. | This file is part of the Roundcube Webmail client |
  7. | Copyright (C) 2005-2012, The Roundcube Dev Team |
  8. | Copyright (C) 2011-2012, Kolab Systems AG |
  9. | |
  10. | Licensed under the GNU General Public License version 3 or |
  11. | any later version with exceptions for skins & plugins. |
  12. | See the README file for a full license statement. |
  13. | |
  14. | PURPOSE: |
  15. | Image resizer and converter |
  16. | |
  17. +-----------------------------------------------------------------------+
  18. | Author: Thomas Bruederli <roundcube@gmail.com> |
  19. | Author: Aleksander Machniak <alec@alec.pl> |
  20. +-----------------------------------------------------------------------+
  21. */
  22. /**
  23. * Image resizer and converter
  24. *
  25. * @package Framework
  26. * @subpackage Utils
  27. */
  28. class rcube_image
  29. {
  30. private $image_file;
  31. const TYPE_GIF = 1;
  32. const TYPE_JPG = 2;
  33. const TYPE_PNG = 3;
  34. const TYPE_TIF = 4;
  35. public static $extensions = array(
  36. self::TYPE_GIF => 'gif',
  37. self::TYPE_JPG => 'jpg',
  38. self::TYPE_PNG => 'png',
  39. self::TYPE_TIF => 'tif',
  40. );
  41. function __construct($filename)
  42. {
  43. $this->image_file = $filename;
  44. }
  45. /**
  46. * Get image properties.
  47. *
  48. * @return mixed Hash array with image props like type, width, height
  49. */
  50. public function props()
  51. {
  52. // use GD extension
  53. if (function_exists('getimagesize') && ($imsize = @getimagesize($this->image_file))) {
  54. $width = $imsize[0];
  55. $height = $imsize[1];
  56. $gd_type = $imsize['2'];
  57. $type = image_type_to_extension($imsize['2'], false);
  58. }
  59. // use ImageMagick
  60. if (!$type && ($data = $this->identify())) {
  61. list($type, $width, $height) = $data;
  62. }
  63. if ($type) {
  64. return array(
  65. 'type' => $type,
  66. 'gd_type' => $gd_type,
  67. 'width' => $width,
  68. 'height' => $height,
  69. );
  70. }
  71. }
  72. /**
  73. * Resize image to a given size
  74. *
  75. * @param int $size Max width/height size
  76. * @param string $filename Output filename
  77. * @param boolean $browser_compat Convert to image type displayable by any browser
  78. *
  79. * @return mixed Output type on success, False on failure
  80. */
  81. public function resize($size, $filename = null, $browser_compat = false)
  82. {
  83. $result = false;
  84. $rcube = rcube::get_instance();
  85. $convert = $rcube->config->get('im_convert_path', false);
  86. $props = $this->props();
  87. if (!$filename) {
  88. $filename = $this->image_file;
  89. }
  90. // use Imagemagick
  91. if ($convert) {
  92. $p['out'] = $filename;
  93. $p['in'] = $this->image_file;
  94. $p['size'] = $size.'x'.$size;
  95. $type = $props['type'];
  96. if (!$type && ($data = $this->identify())) {
  97. $type = $data[0];
  98. }
  99. $type = strtr($type, array("jpeg" => "jpg", "tiff" => "tif", "ps" => "eps", "ept" => "eps"));
  100. $p['intype'] = $type;
  101. // convert to an image format every browser can display
  102. if ($browser_compat && !in_array($type, array('jpg','gif','png'))) {
  103. $type = 'jpg';
  104. }
  105. $p += array('type' => $type, 'types' => "bmp,eps,gif,jp2,jpg,png,svg,tif", 'quality' => 75);
  106. $p['-opts'] = array('-resize' => $p['size'].'>');
  107. if (in_array($type, explode(',', $p['types']))) { // Valid type?
  108. $result = rcube::exec($convert . ' 2>&1 -flatten -auto-orient -colorspace RGB -quality {quality} {-opts} {intype}:{in} {type}:{out}', $p);
  109. }
  110. if ($result === '') {
  111. return $type;
  112. }
  113. }
  114. // use GD extension
  115. $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
  116. if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) {
  117. if ($props['gd_type'] == IMAGETYPE_JPEG) {
  118. $image = imagecreatefromjpeg($this->image_file);
  119. }
  120. elseif($props['gd_type'] == IMAGETYPE_GIF) {
  121. $image = imagecreatefromgif($this->image_file);
  122. }
  123. elseif($props['gd_type'] == IMAGETYPE_PNG) {
  124. $image = imagecreatefrompng($this->image_file);
  125. }
  126. $scale = $size / max($props['width'], $props['height']);
  127. $width = $props['width'] * $scale;
  128. $height = $props['height'] * $scale;
  129. $new_image = imagecreatetruecolor($width, $height);
  130. // Fix transparency of gif/png image
  131. if ($props['gd_type'] != IMAGETYPE_JPEG) {
  132. imagealphablending($new_image, false);
  133. imagesavealpha($new_image, true);
  134. $transparent = imagecolorallocatealpha($new_image, 255, 255, 255, 127);
  135. imagefilledrectangle($new_image, 0, 0, $width, $height, $transparent);
  136. }
  137. imagecopyresampled($new_image, $image, 0, 0, 0, 0, $width, $height, $props['width'], $props['height']);
  138. $image = $new_image;
  139. if ($props['gd_type'] == IMAGETYPE_JPEG) {
  140. $result = imagejpeg($image, $filename, 75);
  141. $type = 'jpg';
  142. }
  143. elseif($props['gd_type'] == IMAGETYPE_GIF) {
  144. $result = imagegif($image, $filename);
  145. $type = 'gid';
  146. }
  147. elseif($props['gd_type'] == IMAGETYPE_PNG) {
  148. $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
  149. $type = 'png';
  150. }
  151. if ($result) {
  152. return $type;
  153. }
  154. }
  155. // @TODO: print error to the log?
  156. return false;
  157. }
  158. /**
  159. * Convert image to a given type
  160. *
  161. * @param int $type Destination file type (see class constants)
  162. * @param string $filename Output filename (if empty, original file will be used
  163. * and filename extension will be modified)
  164. *
  165. * @return bool True on success, False on failure
  166. */
  167. public function convert($type, $filename = null)
  168. {
  169. $rcube = rcube::get_instance();
  170. $convert = $rcube->config->get('im_convert_path', false);
  171. if (!$filename) {
  172. $filename = $this->image_file;
  173. // modify extension
  174. if ($extension = self::$extensions[$type]) {
  175. $filename = preg_replace('/\.[^.]+$/', '', $filename) . '.' . $extension;
  176. }
  177. }
  178. // use ImageMagick
  179. if ($convert) {
  180. $p['in'] = $this->image_file;
  181. $p['out'] = $filename;
  182. $p['type'] = self::$extensions[$type];
  183. $result = rcube::exec($convert . ' 2>&1 -colorspace RGB -quality 75 {in} {type}:{out}', $p);
  184. if ($result === '') {
  185. return true;
  186. }
  187. }
  188. // use GD extension (TIFF isn't supported)
  189. $props = $this->props();
  190. $gd_types = array(IMAGETYPE_JPEG, IMAGETYPE_GIF, IMAGETYPE_PNG);
  191. if ($props['gd_type'] && in_array($props['gd_type'], $gd_types)) {
  192. if ($props['gd_type'] == IMAGETYPE_JPEG) {
  193. $image = imagecreatefromjpeg($this->image_file);
  194. }
  195. else if ($props['gd_type'] == IMAGETYPE_GIF) {
  196. $image = imagecreatefromgif($this->image_file);
  197. }
  198. else if ($props['gd_type'] == IMAGETYPE_PNG) {
  199. $image = imagecreatefrompng($this->image_file);
  200. }
  201. if ($type == self::TYPE_JPG) {
  202. $result = imagejpeg($image, $filename, 75);
  203. }
  204. else if ($type == self::TYPE_GIF) {
  205. $result = imagegif($image, $filename);
  206. }
  207. else if ($type == self::TYPE_PNG) {
  208. $result = imagepng($image, $filename, 6, PNG_ALL_FILTERS);
  209. }
  210. }
  211. // @TODO: print error to the log?
  212. return false;
  213. }
  214. /**
  215. * Identify command handler.
  216. */
  217. private function identify()
  218. {
  219. $rcube = rcube::get_instance();
  220. if ($cmd = $rcube->config->get('im_identify_path')) {
  221. $args = array('in' => $this->image_file, 'format' => "%m %[fx:w] %[fx:h]");
  222. $id = rcube::exec($cmd. ' 2>/dev/null -format {format} {in}', $args);
  223. if ($id) {
  224. return explode(' ', strtolower($id));
  225. }
  226. }
  227. }
  228. }