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