image.lib.php 12 KB

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