You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
11 KiB

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