tcpdf_images.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. <?php
  2. //============================================================+
  3. // File name : tcpdf_images.php
  4. // Version : 1.0.005
  5. // Begin : 2002-08-03
  6. // Last Update : 2014-11-15
  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-2014 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.005
  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.005
  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. * @var string[]
  57. */
  58. public static $svginheritprop = array('clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cursor', 'direction', 'display', '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');
  59. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  60. /**
  61. * Return the image type given the file name or array returned by getimagesize() function.
  62. * @param string $imgfile image file name
  63. * @param array $iminfo array of image information returned by getimagesize() function.
  64. * @return string image type
  65. * @since 4.8.017 (2009-11-27)
  66. * @public static
  67. */
  68. public static function getImageFileType($imgfile, $iminfo=array()) {
  69. $type = '';
  70. if (isset($iminfo['mime']) AND !empty($iminfo['mime'])) {
  71. $mime = explode('/', $iminfo['mime']);
  72. if ((count($mime) > 1) AND ($mime[0] == 'image') AND (!empty($mime[1]))) {
  73. $type = strtolower(trim($mime[1]));
  74. }
  75. }
  76. if (empty($type)) {
  77. $type = strtolower(trim(pathinfo(parse_url($imgfile, PHP_URL_PATH), PATHINFO_EXTENSION)));
  78. }
  79. if ($type == 'jpg') {
  80. $type = 'jpeg';
  81. }
  82. return $type;
  83. }
  84. /**
  85. * Set the transparency for the given GD image.
  86. * @param resource $new_image GD image object
  87. * @param resource $image GD image object.
  88. * @return resource GD image object $new_image
  89. * @since 4.9.016 (2010-04-20)
  90. * @public static
  91. */
  92. public static function setGDImageTransparency($new_image, $image) {
  93. // default transparency color (white)
  94. $tcol = array('red' => 255, 'green' => 255, 'blue' => 255);
  95. // transparency index
  96. $tid = imagecolortransparent($image);
  97. $palletsize = imagecolorstotal($image);
  98. if (($tid >= 0) AND ($tid < $palletsize)) {
  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 resource $image Image object.
  111. * @param string $tempfile Temporary file name.
  112. * return image PNG image object.
  113. * @since 4.9.016 (2010-04-20)
  114. * @public static
  115. */
  116. public static function _toPNG($image, $tempfile) {
  117. // turn off interlaced mode
  118. imageinterlace($image, 0);
  119. // create temporary PNG image
  120. imagepng($image, $tempfile);
  121. // remove image from memory
  122. imagedestroy($image);
  123. // get PNG image data
  124. $retvars = self::_parsepng($tempfile);
  125. // tidy up by removing temporary image
  126. unlink($tempfile);
  127. return $retvars;
  128. }
  129. /**
  130. * Convert the loaded image to a JPEG and then return a structure for the PDF creator.
  131. * This function requires GD library and write access to the directory defined on K_PATH_CACHE constant.
  132. * @param resource $image Image object.
  133. * @param int $quality JPEG quality.
  134. * @param string $tempfile Temporary file name.
  135. * return array|false image JPEG image object.
  136. * @public static
  137. */
  138. public static function _toJPEG($image, $quality, $tempfile) {
  139. imagejpeg($image, $tempfile, $quality);
  140. imagedestroy($image);
  141. $retvars = self::_parsejpeg($tempfile);
  142. // tidy up by removing temporary image
  143. unlink($tempfile);
  144. return $retvars;
  145. }
  146. /**
  147. * Extract info from a JPEG file without using the GD library.
  148. * @param string $file image file to parse
  149. * @return array|false structure containing the image data
  150. * @public static
  151. */
  152. public static function _parsejpeg($file) {
  153. // check if is a local file
  154. if (!@TCPDF_STATIC::file_exists($file)) {
  155. return false;
  156. }
  157. $a = getimagesize($file);
  158. if (empty($a)) {
  159. //Missing or incorrect image file
  160. return false;
  161. }
  162. if ($a[2] != 2) {
  163. // Not a JPEG file
  164. return false;
  165. }
  166. // bits per pixel
  167. $bpc = isset($a['bits']) ? intval($a['bits']) : 8;
  168. // number of image channels
  169. if (!isset($a['channels'])) {
  170. $channels = 3;
  171. } else {
  172. $channels = intval($a['channels']);
  173. }
  174. // default colour space
  175. switch ($channels) {
  176. case 1: {
  177. $colspace = 'DeviceGray';
  178. break;
  179. }
  180. case 3: {
  181. $colspace = 'DeviceRGB';
  182. break;
  183. }
  184. case 4: {
  185. $colspace = 'DeviceCMYK';
  186. break;
  187. }
  188. default: {
  189. $channels = 3;
  190. $colspace = 'DeviceRGB';
  191. break;
  192. }
  193. }
  194. // get file content
  195. $data = file_get_contents($file);
  196. // check for embedded ICC profile
  197. $icc = array();
  198. $offset = 0;
  199. while (($pos = strpos($data, "ICC_PROFILE\0", $offset)) !== false) {
  200. // get ICC sequence length
  201. $length = (TCPDF_STATIC::_getUSHORT($data, ($pos - 2)) - 16);
  202. // marker sequence number
  203. $msn = max(1, ord($data[($pos + 12)]));
  204. // number of markers (total of APP2 used)
  205. $nom = max(1, ord($data[($pos + 13)]));
  206. // get sequence segment
  207. $icc[($msn - 1)] = substr($data, ($pos + 14), $length);
  208. // move forward to next sequence
  209. $offset = ($pos + 14 + $length);
  210. }
  211. // order and compact ICC segments
  212. if (count($icc) > 0) {
  213. ksort($icc);
  214. $icc = implode('', $icc);
  215. if ((ord($icc[36]) != 0x61) OR (ord($icc[37]) != 0x63) OR (ord($icc[38]) != 0x73) OR (ord($icc[39]) != 0x70)) {
  216. // invalid ICC profile
  217. $icc = false;
  218. }
  219. } else {
  220. $icc = false;
  221. }
  222. return array('w' => $a[0], 'h' => $a[1], 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'DCTDecode', 'data' => $data);
  223. }
  224. /**
  225. * Extract info from a PNG file without using the GD library.
  226. * @param string $file image file to parse
  227. * @return array|false structure containing the image data
  228. * @public static
  229. */
  230. public static function _parsepng($file) {
  231. $f = @fopen($file, 'rb');
  232. if ($f === false) {
  233. // Can't open image file
  234. return false;
  235. }
  236. //Check signature
  237. if (fread($f, 8) != chr(137).'PNG'.chr(13).chr(10).chr(26).chr(10)) {
  238. // Not a PNG file
  239. return false;
  240. }
  241. //Read header chunk
  242. fread($f, 4);
  243. if (fread($f, 4) != 'IHDR') {
  244. //Incorrect PNG file
  245. return false;
  246. }
  247. $w = TCPDF_STATIC::_freadint($f);
  248. $h = TCPDF_STATIC::_freadint($f);
  249. $bpc = ord(fread($f, 1));
  250. $ct = ord(fread($f, 1));
  251. if ($ct == 0) {
  252. $colspace = 'DeviceGray';
  253. } elseif ($ct == 2) {
  254. $colspace = 'DeviceRGB';
  255. } elseif ($ct == 3) {
  256. $colspace = 'Indexed';
  257. } else {
  258. // alpha channel
  259. fclose($f);
  260. return 'pngalpha';
  261. }
  262. if (ord(fread($f, 1)) != 0) {
  263. // Unknown compression method
  264. fclose($f);
  265. return false;
  266. }
  267. if (ord(fread($f, 1)) != 0) {
  268. // Unknown filter method
  269. fclose($f);
  270. return false;
  271. }
  272. if (ord(fread($f, 1)) != 0) {
  273. // Interlacing not supported
  274. fclose($f);
  275. return false;
  276. }
  277. fread($f, 4);
  278. $channels = ($ct == 2 ? 3 : 1);
  279. $parms = '/DecodeParms << /Predictor 15 /Colors '.$channels.' /BitsPerComponent '.$bpc.' /Columns '.$w.' >>';
  280. //Scan chunks looking for palette, transparency and image data
  281. $pal = '';
  282. $trns = '';
  283. $data = '';
  284. $icc = false;
  285. $n = TCPDF_STATIC::_freadint($f);
  286. do {
  287. $type = fread($f, 4);
  288. if ($type == 'PLTE') {
  289. // read palette
  290. $pal = TCPDF_STATIC::rfread($f, $n);
  291. fread($f, 4);
  292. } elseif ($type == 'tRNS') {
  293. // read transparency info
  294. $t = TCPDF_STATIC::rfread($f, $n);
  295. if ($ct == 0) { // DeviceGray
  296. $trns = array(ord($t[1]));
  297. } elseif ($ct == 2) { // DeviceRGB
  298. $trns = array(ord($t[1]), ord($t[3]), ord($t[5]));
  299. } else { // Indexed
  300. if ($n > 0) {
  301. $trns = array();
  302. for ($i = 0; $i < $n; ++ $i) {
  303. $trns[] = ord($t[$i]);
  304. }
  305. }
  306. }
  307. fread($f, 4);
  308. } elseif ($type == 'IDAT') {
  309. // read image data block
  310. $data .= TCPDF_STATIC::rfread($f, $n);
  311. fread($f, 4);
  312. } elseif ($type == 'iCCP') {
  313. // skip profile name
  314. $len = 0;
  315. while ((ord(fread($f, 1)) != 0) AND ($len < 80)) {
  316. ++$len;
  317. }
  318. // get compression method
  319. if (ord(fread($f, 1)) != 0) {
  320. // Unknown filter method
  321. fclose($f);
  322. return false;
  323. }
  324. // read ICC Color Profile
  325. $icc = TCPDF_STATIC::rfread($f, ($n - $len - 2));
  326. // decompress profile
  327. $icc = gzuncompress($icc);
  328. fread($f, 4);
  329. } elseif ($type == 'IEND') {
  330. break;
  331. } else {
  332. TCPDF_STATIC::rfread($f, $n + 4);
  333. }
  334. $n = TCPDF_STATIC::_freadint($f);
  335. } while ($n);
  336. if (($colspace == 'Indexed') AND (empty($pal))) {
  337. // Missing palette
  338. fclose($f);
  339. return false;
  340. }
  341. fclose($f);
  342. return array('w' => $w, 'h' => $h, 'ch' => $channels, 'icc' => $icc, 'cs' => $colspace, 'bpc' => $bpc, 'f' => 'FlateDecode', 'parms' => $parms, 'pal' => $pal, 'trns' => $trns, 'data' => $data);
  343. }
  344. } // END OF TCPDF_IMAGES CLASS
  345. //============================================================+
  346. // END OF FILE
  347. //============================================================+