tcpdf_images.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. <?php
  2. //============================================================+
  3. // File name : tcpdf_images.php
  4. // Version : 1.0.002
  5. // Begin : 2002-08-03
  6. // Last Update : 2013-11-24
  7. // Author : Nicola Asuni - Tecnick.com LTD - www.tecnick.com - info@tecnick.com
  8. // License : GNU-LGPL v3 (http://www.gnu.org/copyleft/lesser.html)
  9. // -------------------------------------------------------------------
  10. // Copyright (C) 2002-2013 Nicola Asuni - Tecnick.com LTD
  11. //
  12. // This file is part of TCPDF software library.
  13. //
  14. // TCPDF is free software: you can redistribute it and/or modify it
  15. // under the terms of the GNU Lesser General Public License as
  16. // published by the Free Software Foundation, either version 3 of the
  17. // License, or (at your option) any later version.
  18. //
  19. // TCPDF is distributed in the hope that it will be useful, but
  20. // WITHOUT ANY WARRANTY; without even the implied warranty of
  21. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  22. // See the GNU Lesser General Public License for more details.
  23. //
  24. // You should have received a copy of the License
  25. // along with TCPDF. If not, see
  26. // <http://www.tecnick.com/pagefiles/tcpdf/LICENSE.TXT>.
  27. //
  28. // See LICENSE.TXT file for more information.
  29. // -------------------------------------------------------------------
  30. //
  31. // Description :
  32. // Static image methods used by the TCPDF class.
  33. //
  34. //============================================================+
  35. /**
  36. * @file
  37. * This is a PHP class that contains static image methods for the TCPDF class.<br>
  38. * @package com.tecnick.tcpdf
  39. * @author Nicola Asuni
  40. * @version 1.0.002
  41. */
  42. /**
  43. * @class TCPDF_IMAGES
  44. * Static image methods used by the TCPDF class.
  45. * @package com.tecnick.tcpdf
  46. * @brief PHP class for generating PDF documents without requiring external extensions.
  47. * @version 1.0.002
  48. * @author Nicola Asuni - info@tecnick.com
  49. */
  50. class TCPDF_IMAGES {
  51. /**
  52. * Array of hinheritable SVG properties.
  53. * @since 5.0.000 (2010-05-02)
  54. * @public static
  55. */
  56. public static $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'fill', 'fill-opacity', 'fill-rule', 'font', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical', 'image-rendering', 'kerning', 'letter-spacing', 'marker', 'marker-end', 'marker-mid', 'marker-start', 'pointer-events', 'shape-rendering', 'stroke', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'text-anchor', 'text-rendering', 'visibility', 'word-spacing', 'writing-mode');
  57. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  58. /**
  59. * Return the image type given the file name or array returned by getimagesize() function.
  60. * @param $imgfile (string) image file name
  61. * @param $iminfo (array) array of image information returned by getimagesize() function.
  62. * @return string image type
  63. * @since 4.8.017 (2009-11-27)
  64. * @public static
  65. */
  66. public static function getImageFileType($imgfile, $iminfo=array()) {
  67. $type = '';
  68. if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) {
  69. $mime = explode('/', $iminfo['mime']);
  70. if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) {
  71. $type = strtolower(trim($mime[1]));
  72. }
  73. }
  74. if (empty($type)) {
  75. $fileinfo = pathinfo($imgfile);
  76. if (isset($fileinfo['extension']) AND (!TCPDF_STATIC::empty_string($fileinfo['extension']))) {
  77. $type = strtolower(trim($fileinfo['extension']));
  78. }
  79. }
  80. if ($type == 'jpg') {
  81. $type = 'jpeg';
  82. }
  83. return $type;
  84. }
  85. /**
  86. * Set the transparency for the given GD image.
  87. * @param $new_image (image) GD image object
  88. * @param $image (image) GD image object.
  89. * return GD image object.
  90. * @since 4.9.016 (2010-04-20)
  91. * @public static
  92. */
  93. public static function setGDImageTransparency($new_image, $image) {
  94. // transparency index
  95. $tid = imagecolortransparent($image);
  96. // default transparency color
  97. $tcol = array('red' => 255, 'green' => 255, 'blue' => 255);
  98. if ($tid >= 0) {
  99. // get the colors for the transparency index
  100. $tcol = imagecolorsforindex($image, $tid);
  101. }
  102. $tid = imagecolorallocate($new_image, $tcol['red'], $tcol['green'], $tcol['blue']);
  103. imagefill($new_image, 0, 0, $tid);
  104. imagecolortransparent($new_image, $tid);
  105. return $new_image;
  106. }
  107. /**
  108. * Convert the loaded image to a PNG and then return a structure for the PDF creator.
  109. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
  110. * @param $image (image) Image object.
  111. * return image PNG image object.
  112. * @since 4.9.016 (2010-04-20)
  113. * @public static
  114. */
  115. public static function _toPNG($image) {
  116. // set temporary image file name
  117. $tempname = TCPDF_STATIC::getObjFilename('img');
  118. // turn off interlaced mode
  119. imageinterlace($image, 0);
  120. // create temporary PNG image
  121. imagepng($image, $tempname);
  122. // remove image from memory
  123. imagedestroy($image);
  124. // get PNG image data
  125. $retvars = self::_parsepng($tempname);
  126. // tidy up by removing temporary image
  127. unlink($tempname);
  128. return $retvars;
  129. }
  130. /**
  131. * Convert the loaded image to a JPEG and then return a structure for the PDF creator.
  132. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
  133. * @param $image (image) Image object.
  134. * @param $quality (int) JPEG quality.
  135. * return image JPEG image object.
  136. * @public static
  137. */
  138. public static function _toJPEG($image, $quality) {
  139. $tempname = TCPDF_STATIC::getObjFilename('img');
  140. imagejpeg($image, $tempname, $quality);
  141. imagedestroy($image);
  142. $retvars = self::_parsejpeg($tempname);
  143. // tidy up by removing temporary image
  144. unlink($tempname);
  145. return $retvars;
  146. }
  147. /**
  148. * Extract info from a JPEG file without using the GD library.
  149. * @param $file (string) image file to parse
  150. * @return array structure containing the image data
  151. * @public static
  152. */
  153. public static function _parsejpeg($file) {
  154. $a = getimagesize($file);
  155. if (empty($a)) {
  156. //Missing or incorrect image file
  157. return false;
  158. }
  159. if ($a[2] != 2) {
  160. // Not a JPEG file
  161. return false;
  162. }
  163. // bits per pixel
  164. $bpc = isset($a['bits']) ? intval($a['bits']) : 8;
  165. // number of image channels
  166. if (!isset($a['channels'])) {
  167. $channels = 3;
  168. } else {
  169. $channels = intval($a['channels']);
  170. }
  171. // default colour space
  172. switch ($channels) {
  173. case 1: {
  174. $colspace = 'DeviceGray';
  175. break;
  176. }
  177. case 3: {
  178. $colspace = 'DeviceRGB';
  179. break;
  180. }
  181. case 4: {
  182. $colspace = 'DeviceCMYK';
  183. break;
  184. }
  185. default: {
  186. $channels = 3;
  187. $colspace = 'DeviceRGB';
  188. break;
  189. }
  190. }
  191. // get file content
  192. $data = file_get_contents($file);
  193. // check for embedded ICC profile
  194. $icc = array();
  195. $offset = 0;
  196. while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
  197. // get ICC sequence length
  198. $length = (TCPDF_STATIC::_getUSHORT($data, ($pos - 2)) - 16);
  199. // marker sequence number
  200. $msn = max(1, ord($data[($pos + 12)]));
  201. // number of markers (total of APP2 used)
  202. $nom = max(1, ord($data[($pos + 13)]));
  203. // get sequence segment
  204. $icc[($msn - 1)] = substr($data, ($pos + 14), $length);
  205. // move forward to next sequence
  206. $offset = ($pos + 14 + $length);
  207. }
  208. // order and compact ICC segments
  209. if (count($icc) > 0) {
  210. ksort($icc);
  211. $icc = implode('', $icc);
  212. if ((ord($icc{36}) != 0x61) OR (ord($icc{37}) != 0x63) OR (ord($icc{38}) != 0x73) OR (ord($icc{39}) != 0x70)) {
  213. // invalid ICC profile
  214. $icc = false;
  215. }
  216. } else {
  217. $icc = false;
  218. }
  219. return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
  220. }
  221. /**
  222. * Extract info from a PNG file without using the GD library.
  223. * @param $file (string) image file to parse
  224. * @return array structure containing the image data
  225. * @public static
  226. */
  227. public static function _parsepng($file) {
  228. $f = @fopen($file, 'rb');
  229. if ($f === false) {
  230. // Can't open image file
  231. return false;
  232. }
  233. //Check signature
  234. if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
  235. // Not a PNG file
  236. return false;
  237. }
  238. //Read header chunk
  239. fread($f, 4);
  240. if (fread($f, 4) != 'IHDR') {
  241. //Incorrect PNG file
  242. return false;
  243. }
  244. $w = TCPDF_STATIC::_freadint($f);
  245. $h = TCPDF_STATIC::_freadint($f);
  246. $bpc = ord(fread($f, 1));
  247. $ct = ord(fread($f, 1));
  248. if ($ct == 0) {
  249. $colspace = 'DeviceGray';
  250. } elseif ($ct == 2) {
  251. $colspace = 'DeviceRGB';
  252. } elseif ($ct == 3) {
  253. $colspace = 'Indexed';
  254. } else {
  255. // alpha channel
  256. fclose($f);
  257. return 'pngalpha';
  258. }
  259. if (ord(fread($f, 1)) != 0) {
  260. // Unknown compression method
  261. fclose($f);
  262. return false;
  263. }
  264. if (ord(fread($f, 1)) != 0) {
  265. // Unknown filter method
  266. fclose($f);
  267. return false;
  268. }
  269. if (ord(fread($f, 1)) != 0) {
  270. // Interlacing not supported
  271. fclose($f);
  272. return false;
  273. }
  274. fread($f, 4);
  275. $channels = ($ct == 2 ? 3 : 1);
  276. $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
  277. //Scan chunks looking for palette, transparency and image data
  278. $pal = '';
  279. $trns = '';
  280. $data = '';
  281. $icc = false;
  282. do {
  283. $n = TCPDF_STATIC::_freadint($f);
  284. $type = fread($f, 4);
  285. if ($type == 'PLTE') {
  286. // read palette
  287. $pal = TCPDF_STATIC::rfread($f, $n);
  288. fread($f, 4);
  289. } elseif ($type == 'tRNS') {
  290. // read transparency info
  291. $t = TCPDF_STATIC::rfread($f, $n);
  292. if ($ct == 0) {
  293. $trns = array(ord($t{1}));
  294. } elseif ($ct == 2) {
  295. $trns = array(ord($t{1}), ord($t{3}), ord($t{5}));
  296. } else {
  297. $pos = strpos($t, chr(0));
  298. if ($pos !== false) {
  299. $trns = array($pos);
  300. }
  301. }
  302. fread($f, 4);
  303. } elseif ($type == 'IDAT') {
  304. // read image data block
  305. $data .= TCPDF_STATIC::rfread($f, $n);
  306. fread($f, 4);
  307. } elseif ($type == 'iCCP') {
  308. // skip profile name
  309. $len = 0;
  310. while ((ord(fread($f, 1)) > 0) AND ($len < 80)) {
  311. ++$len;
  312. }
  313. // skip null separator
  314. fread($f, 1);
  315. // get compression method
  316. if (ord(fread($f, 1)) != 0) {
  317. // Unknown filter method
  318. fclose($f);
  319. return false;
  320. }
  321. // read ICC Color Profile
  322. $icc = TCPDF_STATIC::rfread($f, ($n - $len - 2));
  323. // decompress profile
  324. $icc = gzuncompress($icc);
  325. fread($f, 4);
  326. } elseif ($type == 'IEND') {
  327. break;
  328. } else {
  329. TCPDF_STATIC::rfread($f, $n + 4);
  330. }
  331. } while ($n);
  332. if (($colspace == 'Indexed') AND (empty($pal))) {
  333. // Missing palette
  334. fclose($f);
  335. return false;
  336. }
  337. fclose($f);
  338. return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
  339. }
  340. } // END OF TCPDF_IMAGES CLASS
  341. //============================================================+
  342. // END OF FILE
  343. //============================================================+