image.lib.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. /**
  4. * This class provides a layer to manage images
  5. * @author Julio Montoya <gugli100@gmail.com>
  6. */
  7. //@todo move in a DB configuration setting
  8. define('IMAGE_PROCESSOR', 'gd'); // imagick or gd strings
  9. class Image {
  10. var $image_wrapper = null;
  11. function __construct($path) {
  12. $path = preg_match(VALID_WEB_PATH, $path) ? (api_is_internal_path($path) ? api_get_path(TO_SYS, $path) : $path) : $path;
  13. if (IMAGE_PROCESSOR == 'gd') {
  14. $this->image_wrapper = new GDWrapper($path);
  15. } else {
  16. $this->image_wrapper = new ImagickWrapper($path);
  17. }
  18. }
  19. public function resize($thumbw, $thumbh, $border = 0, $specific_size = false) {
  20. $this->image_wrapper->resize($thumbw, $thumbh, $border, $specific_size );
  21. }
  22. public function send_image($file = '', $compress = -1, $convert_file_to = null) {
  23. return $this->image_wrapper->send_image($file, $compress, $convert_file_to);
  24. }
  25. public function get_image_size() {
  26. return $this->image_wrapper->get_image_size();
  27. }
  28. public function get_image_info() {
  29. return $this->image_wrapper->get_image_info();
  30. }
  31. }
  32. abstract class ImageWrapper {
  33. var $debug = true;
  34. var $path;
  35. var $width;
  36. var $height;
  37. var $type;
  38. var $allowed_extensions = array('jpeg', 'jpg', 'png', 'gif');
  39. var $image_validated = false;
  40. public function __construct($path) {
  41. if (empty($path)) {
  42. return false;
  43. }
  44. $this->path = preg_match(VALID_WEB_PATH, $path) ? (api_is_internal_path($path) ? api_get_path(TO_SYS, $path) : $path) : $path;
  45. $this->set_image_wrapper(); //Creates image obj
  46. }
  47. abstract function set_image_wrapper();
  48. abstract function fill_image_info();
  49. abstract function get_image_size();
  50. abstract function resize($thumbw, $thumbh, $border, $specific_size = false);
  51. abstract function send_image($file = '', $compress = -1, $convert_file_to = null);
  52. public function get_image_info() {
  53. return array('width' => $this->width,
  54. 'height' => $this->height,
  55. 'type' => $this->type
  56. );
  57. }
  58. }
  59. /**
  60. * Imagick Chamilo wrapper
  61. *
  62. * @author jmontoya
  63. *
  64. */
  65. class ImagickWrapper extends ImageWrapper {
  66. var $image;
  67. var $filter = Imagick::FILTER_LANCZOS;
  68. public function __construct($path) {
  69. parent::__construct($path);
  70. }
  71. public function set_image_wrapper() {
  72. try {
  73. $this->image = new Imagick($this->path);
  74. if ($this->image) {
  75. $this->fill_image_info(); //Fills height, width and type
  76. }
  77. if ($this->debug) error_log('set_image_wrapper loaded');
  78. } catch(ImagickException $e) {
  79. if ($this->debug) error_log($e->getMessage());
  80. }
  81. }
  82. public function fill_image_info() {
  83. $image_info = $this->image->identifyImage();
  84. $this->width = $image_info['geometry']['width'];
  85. $this->height = $image_info['geometry']['height'];
  86. $this->type = strtolower($this->image->getImageFormat());
  87. if (in_array($this->type, $this->allowed_extensions)) {
  88. $this->image_validated = true;
  89. if ($this->debug) error_log('image_validated true');
  90. }
  91. }
  92. public function get_image_size() {
  93. if ($this->image_validated) {
  94. return $imagesize = $this->image->getImageGeometry();
  95. }
  96. }
  97. //@todo implement border logic case for Imagick
  98. public function resize($thumbw, $thumbh, $border, $specific_size = false) {
  99. if (!$this->image_validated) return false;
  100. if ($specific_size) {
  101. $width = $thumbw;
  102. $height = $thumbh;
  103. } else {
  104. $scale = ($this->width > 0 && $this->height > 0) ? min($thumbw / $this->width, $thumbh / $this->height) : 0;
  105. $width = (int)($this->width * $scale);
  106. $height = (int)($this->height * $scale);
  107. }
  108. $result = $this->image->resizeImage($width, $height, $this->filter, 1);
  109. $this->width = $thumbw;
  110. $this->height = $thumbh;
  111. }
  112. public function send_image($file = '', $compress = -1, $convert_file_to = null) {
  113. if (!$this->image_validated) return false;
  114. $type = $this->type;
  115. if (!empty($convert_file_to) && in_array($convert_file_to, $this->allowed_extensions)) {
  116. $type = $convert_file_to;
  117. }
  118. switch ($type) {
  119. case 'jpeg':
  120. case 'jpg':
  121. if (!$file) header("Content-type: image/jpeg");
  122. break;
  123. case 'png':
  124. if (!$file) header("Content-type: image/png");
  125. break;
  126. case 'gif':
  127. if (!$file) header("Content-type: image/gif");
  128. break;
  129. }
  130. $result = false;
  131. try {
  132. $result = $this->image->writeImage($file);
  133. } catch(ImagickException $e) {
  134. if ($this->debug) error_log($e->getMessage());
  135. }
  136. if (!$file) {
  137. echo $this->image;
  138. $this->image->clear();
  139. $this->image->destroy();
  140. } else {
  141. $this->image->clear();
  142. $this->image->destroy();
  143. return $result;
  144. }
  145. }
  146. }
  147. /**
  148. * php-gd wrapper
  149. *
  150. *
  151. */
  152. class GDWrapper extends ImageWrapper {
  153. var $bg;
  154. function __construct($path) {
  155. parent::__construct($path);
  156. }
  157. public function set_image_wrapper() {
  158. $handler = null;
  159. $this->fill_image_info();
  160. switch ($this->type) {
  161. case 1 :
  162. $handler = @imagecreatefromgif($this->path);
  163. $this->type = 'gif';
  164. break;
  165. case 2 :
  166. $handler = @imagecreatefromjpeg($this->path);
  167. $this->type = 'jpg';
  168. break;
  169. case 3 :
  170. $handler = @imagecreatefrompng($this->path);
  171. $this->type = 'png';
  172. break;
  173. }
  174. if ($handler) {
  175. $this->image_validated = true;
  176. $this->bg = $handler;
  177. @imagealphablending($this->bg, true);
  178. }
  179. }
  180. public function get_image_size() {
  181. return $return_array = array('width'=>$this->width,'height'=>$this->height);
  182. }
  183. public function fill_image_info() {
  184. $image_info = getimagesize($this->path);
  185. $this->width = $image_info[0];
  186. $this->height = $image_info[1];
  187. $this->type = $image_info[2];
  188. }
  189. public function resize($thumbw, $thumbh, $border, $specific_size = false) {
  190. if (!$this->image_validated) return false;
  191. if ($border == 1) {
  192. if ($specific_size) {
  193. $width = $thumbw;
  194. $height = $thumbh;
  195. } else {
  196. $scale = min($thumbw / $this->width, $thumbh / $this->height);
  197. $width = (int)($this->width * $scale);
  198. $height = (int)($this->height * $scale);
  199. }
  200. $deltaw = (int)(($thumbw - $width) / 2);
  201. $deltah = (int)(($thumbh - $height) / 2);
  202. $dst_img = @ImageCreateTrueColor($thumbw, $thumbh);
  203. if (!empty($this->color)) {
  204. @imagefill($dst_img, 0, 0, $this->color);
  205. }
  206. $this->width = $thumbw;
  207. $this->height = $thumbh;
  208. } elseif ($border == 0) {
  209. if ($specific_size) {
  210. $width = $thumbw;
  211. $height = $thumbh;
  212. } else {
  213. $scale = ($this->width > 0 && $this->height > 0) ? min($thumbw / $this->width, $thumbh / $this->height) : 0;
  214. $width = (int)($this->width * $scale);
  215. $height = (int)($this->height * $scale);
  216. }
  217. $deltaw = 0;
  218. $deltah = 0;
  219. $dst_img = @ImageCreateTrueColor($width, $height);
  220. $this->width = $width;
  221. $this->height = $height;
  222. }
  223. $src_img = $this->bg;
  224. @ImageCopyResampled($dst_img, $src_img, $deltaw, $deltah, 0, 0, $width, $height, ImageSX($src_img), ImageSY($src_img));
  225. $this->bg = $dst_img;
  226. @imagedestroy($src_img);
  227. }
  228. public function send_image($file = '', $compress = -1, $convert_file_to = null) {
  229. if (!$this->image_validated) return false;
  230. $type = $this->type;
  231. if (!empty($convert_file_to) && in_array($convert_file_to, $this->allowed_extensions)) {
  232. $type = $convert_file_to;
  233. }
  234. switch ($type) {
  235. case 'jpeg':
  236. case 'jpg':
  237. if (!$file) header("Content-type: image/jpeg");
  238. if ($compress == -1) $compress = 100;
  239. return imagejpeg($this->bg, $file, $compress);
  240. break;
  241. case 'png':
  242. if (!$file) header("Content-type: image/png");
  243. if ($compress != -1) {
  244. @imagetruecolortopalette($this->bg, true, $compress);
  245. }
  246. return imagepng($this->bg, $file, $compress);
  247. break;
  248. case 'gif':
  249. if (!$file) header("Content-type: image/gif");
  250. if ($compress != -1) {
  251. @imagetruecolortopalette($this->bg, true, $compress);
  252. }
  253. return imagegif($this->bg, $file, $compress);
  254. break;
  255. default: return 0;
  256. }
  257. // TODO: Occupied memory is not released, because the following fragment of code is actually dead.
  258. @imagedestroy($this->bg);
  259. //@imagedestroy($this->logo);
  260. }
  261. /*
  262. * @deprecated
  263. *
  264. function addlogo($file) {
  265. $this->logo = image::createimagefromtype($file, 'logo');
  266. @imagealphablending($this->logo , true);
  267. $size = api_getimagesize($file);
  268. $this->logox = $size['width'];
  269. $this->logoy = $size['height'];
  270. }*/
  271. /* @deprecated
  272. function addtext ($text, $x = 0, $y = 0, $size = 12, $angle = 0) {
  273. putenv('GDFONTPATH=' . realpath('.'));
  274. $this->fontfile='verdana';
  275. $text= preg_replace('`(?<!\r)\n`', "\r\n", $text);
  276. $box = @imagettfbbox($size, $angle, $this->fontfile, $text);
  277. if ($x < 0) {
  278. $x = $this->width - max($box[2], $box[4]) + $x;
  279. } else {
  280. $x = max(-$box[0], -$box[6]) + $x;
  281. }
  282. if ($y < 0) {
  283. $y = $this->height - max($box[1], $box[3]) + $y;
  284. } else {
  285. $y = max(-$box[7], -$box[5]) + $y;
  286. }
  287. @imagettftext($this->bg, $size, $angle, $x, $y, $this->color, $this->fontfile , $text);
  288. }
  289. */
  290. /* //@deprecated
  291. function mergelogo($x, $y, $alpha = 100) {
  292. if ($x < 0) $x = $this->width - $this->logox + $x;
  293. if ($y < 0) $y = $this->height - $this->logoy + $y;
  294. return @imagecopymerge($this->bg, $this->logo, $x, $y, 0, 0, $this->logox, $this->logoy, $alpha);
  295. }*/
  296. /* //@deprecated
  297. function makecolor($red, $green, $blue) {
  298. $this->color = @imagecolorallocate($this->bg, $red, $green, $blue);
  299. }
  300. */
  301. /* //@deprecated
  302. function setfont($fontfile) {
  303. $this->fontfile = $fontfile;
  304. }*/
  305. }