Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
84.48% |
196 / 232 |
|
61.54% |
16 / 26 |
CRAP | |
0.00% |
0 / 1 |
Parser | |
84.48% |
196 / 232 |
|
61.54% |
16 / 26 |
108.74 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
createImageFromFile | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
createImageFromStream | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
loadImageFromFile | |
100.00% |
22 / 22 |
|
100.00% |
1 / 1 |
10 | |||
loadImageFromStream | |
97.06% |
33 / 34 |
|
0.00% |
0 / 1 |
11 | |||
setX | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setY | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setIndex | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getX | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getY | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getWidth | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getHeight | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getConvertedImage | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getIndex | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getStream | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
getXObject | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getObjects | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
parse | |
80.00% |
4 / 5 |
|
0.00% |
0 / 1 |
3.07 | |||
parseImageData | |
68.29% |
28 / 41 |
|
0.00% |
0 / 1 |
22.17 | |||
parsePng | |
92.86% |
39 / 42 |
|
0.00% |
0 / 1 |
9.03 | |||
parseJpeg | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
createResource | |
84.62% |
11 / 13 |
|
0.00% |
0 / 1 |
6.13 | |||
convertToJpeg | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
2 | |||
convertImage | |
100.00% |
12 / 12 |
|
100.00% |
1 / 1 |
3 | |||
resizeImage | |
75.00% |
15 / 20 |
|
0.00% |
0 / 1 |
5.39 | |||
readInt | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * Pop PHP Framework (http://www.popphp.org/) |
4 | * |
5 | * @link https://github.com/popphp/popphp-framework |
6 | * @author Nick Sagona, III <dev@nolainteractive.com> |
7 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
8 | * @license http://www.popphp.org/license New BSD License |
9 | */ |
10 | |
11 | /** |
12 | * @namespace |
13 | */ |
14 | namespace Pop\Pdf\Build\Image; |
15 | |
16 | use Pop\Pdf\Build\PdfObject\StreamObject; |
17 | |
18 | /** |
19 | * Pdf image parser class |
20 | * |
21 | * @category Pop |
22 | * @package Pop\Pdf |
23 | * @author Nick Sagona, III <dev@nolainteractive.com> |
24 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
25 | * @license http://www.popphp.org/license New BSD License |
26 | * @version 4.2.0 |
27 | */ |
28 | class Parser |
29 | { |
30 | |
31 | /** |
32 | * Image width |
33 | * @var int |
34 | */ |
35 | protected $width = 0; |
36 | |
37 | /** |
38 | * Image height |
39 | * @var int |
40 | */ |
41 | protected $height = 0; |
42 | |
43 | /** |
44 | * Image resize value |
45 | * @var array |
46 | */ |
47 | protected $resize = null; |
48 | |
49 | /** |
50 | * Image mime |
51 | * @var string |
52 | */ |
53 | protected $mime = null; |
54 | |
55 | /** |
56 | * Image color mode |
57 | * @var mixed |
58 | */ |
59 | protected $colorMode = null; |
60 | |
61 | /** |
62 | * Number of channels in the image |
63 | * @var int |
64 | */ |
65 | protected $channels = 0; |
66 | |
67 | /** |
68 | * Image bit-depth |
69 | * @var int |
70 | */ |
71 | protected $depth = 0; |
72 | |
73 | /** |
74 | * Image basename |
75 | * @var string |
76 | */ |
77 | protected $basename = null; |
78 | |
79 | /** |
80 | * Image filename |
81 | * @var string |
82 | */ |
83 | protected $filename = null; |
84 | |
85 | /** |
86 | * Image extension |
87 | * @var string |
88 | */ |
89 | protected $extension = null; |
90 | |
91 | /** |
92 | * Image fullpath |
93 | * @var string |
94 | */ |
95 | protected $fullpath = null; |
96 | |
97 | /** |
98 | * Image stream |
99 | * @var string |
100 | */ |
101 | protected $stream = null; |
102 | |
103 | /** |
104 | * Image total number of colors |
105 | * @var int |
106 | */ |
107 | protected $colorTotal = 0; |
108 | |
109 | /** |
110 | * Flag for if the image has an alpha channel |
111 | * @var boolean |
112 | */ |
113 | protected $alpha = false; |
114 | |
115 | /** |
116 | * Image data |
117 | * @var mixed |
118 | */ |
119 | protected $imageData = null; |
120 | |
121 | /** |
122 | * Image data length |
123 | * @var int |
124 | */ |
125 | protected $imageDataLength = null; |
126 | |
127 | /** |
128 | * GD image resource |
129 | * @var resource |
130 | */ |
131 | protected $resource = null; |
132 | |
133 | /** |
134 | * Image X Coordinate |
135 | * @var int |
136 | */ |
137 | protected $x = 0; |
138 | |
139 | /** |
140 | * Image Y Coordinate |
141 | * @var int |
142 | */ |
143 | protected $y = 0; |
144 | |
145 | /** |
146 | * Image object index |
147 | * @var int |
148 | */ |
149 | protected $index = null; |
150 | |
151 | /** |
152 | * Image objects |
153 | * @var array |
154 | */ |
155 | protected $objects = []; |
156 | |
157 | /** |
158 | * Converted GIF to PNG image |
159 | * @var string |
160 | */ |
161 | protected $convertedImage = null; |
162 | |
163 | /** |
164 | * Resized image |
165 | * @var string |
166 | */ |
167 | protected $resizedImage = null; |
168 | |
169 | /** |
170 | * Constructor |
171 | * |
172 | * Instantiate a image parser object |
173 | * |
174 | * @param int $x |
175 | * @param int $y |
176 | */ |
177 | public function __construct($x, $y) |
178 | { |
179 | $this->setX($x); |
180 | $this->setY($y); |
181 | } |
182 | |
183 | /** |
184 | * Create image from file |
185 | * |
186 | * @param string $imageFile |
187 | * @param int $x |
188 | * @param int $y |
189 | * @param array $resize |
190 | * @param boolean $preserveResolution |
191 | * @return Parser |
192 | */ |
193 | public static function createImageFromFile($imageFile, $x, $y, array $resize = null, $preserveResolution = false) |
194 | { |
195 | $parser = new self($x, $y); |
196 | $parser->loadImageFromFile($imageFile, $resize, $preserveResolution); |
197 | return $parser; |
198 | } |
199 | |
200 | /** |
201 | * Create image from stream |
202 | * |
203 | * @param string $imageStream |
204 | * @param int $x |
205 | * @param int $y |
206 | * @param array $resize |
207 | * @param boolean $preserveResolution |
208 | * @return Parser |
209 | */ |
210 | public static function createImageFromStream($imageStream, $x, $y, array $resize = null, $preserveResolution = false) |
211 | { |
212 | $parser = new self($x, $y); |
213 | $parser->loadImageFromStream($imageStream, $resize, $preserveResolution); |
214 | return $parser; |
215 | } |
216 | |
217 | /** |
218 | * Load image from file |
219 | * |
220 | * @param string $imageFile |
221 | * @param array $resize |
222 | * @param boolean $preserveResolution |
223 | * @return Parser |
224 | */ |
225 | public function loadImageFromFile($imageFile, array $resize = null, $preserveResolution = false) |
226 | { |
227 | $parts = pathinfo($imageFile); |
228 | $this->fullpath = realpath($imageFile); |
229 | $this->basename = $parts['basename']; |
230 | $this->filename = $parts['filename']; |
231 | $this->extension = (isset($parts['extension']) && ($parts['extension'] != '')) ? $parts['extension'] : null; |
232 | $this->stream = null; |
233 | |
234 | // Convert GIF image to PNG |
235 | if (strtolower($this->extension) == 'gif') { |
236 | $this->convertImage(); |
237 | } else { |
238 | $this->mime = (strtolower($this->extension) == 'png') ? 'image/png' : 'image/jpeg'; |
239 | } |
240 | |
241 | // If resize dimensions are passed |
242 | if ((null !== $resize) && !($preserveResolution)) { |
243 | $this->resizeImage($resize); |
244 | } |
245 | |
246 | $imgSize = getimagesize($this->fullpath); |
247 | |
248 | if (null !== $resize) { |
249 | $this->resize = $resize; |
250 | } |
251 | |
252 | $this->width = $imgSize[0]; |
253 | $this->height = $imgSize[1]; |
254 | $this->channels = (isset($imgSize['channels'])) ? $imgSize['channels'] : null; |
255 | $this->depth = (isset($imgSize['bits'])) ? $imgSize['bits'] : null; |
256 | |
257 | $this->imageData = file_get_contents($this->fullpath); |
258 | $this->imageDataLength = strlen($this->imageData); |
259 | |
260 | $this->parseImageData(); |
261 | |
262 | return $this; |
263 | } |
264 | |
265 | /** |
266 | * Load image from stream |
267 | * |
268 | * @param string $imageStream |
269 | * @param array $resize |
270 | * @param boolean $preserveResolution |
271 | * @return Parser |
272 | */ |
273 | public function loadImageFromStream($imageStream, array $resize = null, $preserveResolution = false) |
274 | { |
275 | $this->stream = $imageStream; |
276 | $imgSize = getimagesizefromstring($this->stream); |
277 | |
278 | $this->fullpath = null; |
279 | |
280 | switch ($imgSize['mime']) { |
281 | case 'image/jpeg': |
282 | $this->basename = 'image.jpg'; |
283 | $this->filename = 'image'; |
284 | $this->extension = 'jpg'; |
285 | break; |
286 | case 'image/gif': |
287 | $this->basename = 'image.gif'; |
288 | $this->filename = 'image'; |
289 | $this->extension = 'gif'; |
290 | break; |
291 | case 'image/png': |
292 | $this->basename = 'image.png'; |
293 | $this->filename = 'image'; |
294 | $this->extension = 'png'; |
295 | break; |
296 | } |
297 | |
298 | // Convert GIF image to PNG |
299 | if (strtolower($this->extension) == 'gif') { |
300 | $this->convertImage(); |
301 | } else { |
302 | $this->mime = (strtolower($this->extension) == 'png') ? 'image/png' : 'image/jpeg'; |
303 | } |
304 | |
305 | // If resize dimensions are passed |
306 | if ((null !== $resize) && !($preserveResolution)) { |
307 | $this->resizeImage($resize); |
308 | } |
309 | |
310 | if (null !== $resize) { |
311 | $this->resize = $resize; |
312 | } |
313 | |
314 | $this->width = $imgSize[0]; |
315 | $this->height = $imgSize[1]; |
316 | $this->channels = (isset($imgSize['channels'])) ? $imgSize['channels'] : null; |
317 | $this->depth = (isset($imgSize['bits'])) ? $imgSize['bits'] : null; |
318 | |
319 | $this->imageData = $this->stream; |
320 | $this->imageDataLength = strlen($this->imageData); |
321 | |
322 | $this->parseImageData(); |
323 | |
324 | return $this; |
325 | } |
326 | |
327 | /** |
328 | * Set the X coordinate |
329 | * |
330 | * @param int $x |
331 | * @return Parser |
332 | */ |
333 | public function setX($x) |
334 | { |
335 | $this->x = (int)$x; |
336 | return $this; |
337 | } |
338 | |
339 | /** |
340 | * Set the Y coordinate |
341 | * |
342 | * @param int $y |
343 | * @return Parser |
344 | */ |
345 | public function setY($y) |
346 | { |
347 | $this->y = (int)$y; |
348 | return $this; |
349 | } |
350 | |
351 | /** |
352 | * Set the image object index |
353 | * |
354 | * @param int $i |
355 | * @return Parser |
356 | */ |
357 | public function setIndex($i) |
358 | { |
359 | $this->index = (int)$i; |
360 | return $this; |
361 | } |
362 | |
363 | /** |
364 | * Get the X coordinate |
365 | * |
366 | * @return int |
367 | */ |
368 | public function getX() |
369 | { |
370 | return $this->x; |
371 | } |
372 | |
373 | /** |
374 | * Get the Y coordinate |
375 | * |
376 | * @return int |
377 | */ |
378 | public function getY() |
379 | { |
380 | return $this->y; |
381 | } |
382 | |
383 | /** |
384 | * Get the width |
385 | * |
386 | * @return int |
387 | */ |
388 | public function getWidth() |
389 | { |
390 | return $this->width; |
391 | } |
392 | |
393 | /** |
394 | * Get the height |
395 | * |
396 | * @return int |
397 | */ |
398 | public function getHeight() |
399 | { |
400 | return $this->height; |
401 | } |
402 | |
403 | /** |
404 | * Get the converted image |
405 | * |
406 | * @return string |
407 | */ |
408 | public function getConvertedImage() |
409 | { |
410 | return $this->convertedImage; |
411 | } |
412 | |
413 | /** |
414 | * Get the image object index |
415 | * |
416 | * @return int |
417 | */ |
418 | public function getIndex() |
419 | { |
420 | return $this->index; |
421 | } |
422 | |
423 | /** |
424 | * Get the image stream |
425 | * |
426 | * @return string |
427 | */ |
428 | public function getStream() |
429 | { |
430 | $width = $this->resize['width'] ?? $this->width; |
431 | $height = $this->resize['height'] ?? $this->height; |
432 | return "\n\nq\n\n1 0 0 1 {$this->x} {$this->y} cm\n{$width} 0 0 {$height} 0 0 cm\n/I{$this->index} Do\n\nQ\n\n"; |
433 | } |
434 | |
435 | /** |
436 | * Get the XObject |
437 | * |
438 | * @return string |
439 | */ |
440 | public function getXObject() |
441 | { |
442 | return "/I{$this->index} {$this->index} 0 R"; |
443 | } |
444 | |
445 | /** |
446 | * Get the image objects |
447 | * |
448 | * @return array |
449 | */ |
450 | public function getObjects() |
451 | { |
452 | if (count($this->objects) == 0) { |
453 | $this->parse(); |
454 | } |
455 | return $this->objects; |
456 | } |
457 | |
458 | /** |
459 | * Parse the image data and create the image objects |
460 | * |
461 | * @throws Exception |
462 | * @return void |
463 | */ |
464 | public function parse() |
465 | { |
466 | if (null === $this->index) { |
467 | throw new Exception('Error: The image index has not been set.'); |
468 | } |
469 | if ($this->mime == 'image/png') { |
470 | $this->parsePng(); |
471 | } else { |
472 | $this->parseJpeg(); |
473 | } |
474 | } |
475 | |
476 | /** |
477 | * Parse image data |
478 | * |
479 | * @return void |
480 | */ |
481 | protected function parseImageData() |
482 | { |
483 | if (substr(strtolower($this->extension), 0, 2) == 'jp') { |
484 | switch ($this->channels) { |
485 | case 1: |
486 | $this->colorMode = 'Gray'; |
487 | break; |
488 | case 3: |
489 | $this->colorMode = 'RGB'; |
490 | break; |
491 | case 4: |
492 | $this->colorMode = 'CMYK'; |
493 | break; |
494 | } |
495 | } else if (strtolower($this->extension) == 'png') { |
496 | $colorType = ord($this->imageData[25]); |
497 | switch ($colorType) { |
498 | case 0: |
499 | $this->channels = 1; |
500 | $this->colorMode = 'Gray'; |
501 | break; |
502 | case 2: |
503 | $this->channels = 3; |
504 | $this->colorMode = 'RGB'; |
505 | break; |
506 | case 3: |
507 | $this->channels = 3; |
508 | $this->colorMode = 'Indexed'; |
509 | break; |
510 | case 4: |
511 | $this->channels = 1; |
512 | $this->colorMode = 'Gray'; |
513 | $this->alpha = true; |
514 | break; |
515 | case 6: |
516 | $this->channels = 3; |
517 | $this->colorMode = 'RGB'; |
518 | $this->alpha = true; |
519 | break; |
520 | } |
521 | } |
522 | |
523 | $this->createResource(); |
524 | |
525 | // Image clean up if the image was converted or resized. |
526 | if ((null !== $this->convertedImage) && file_exists($this->convertedImage)) { |
527 | unlink($this->convertedImage); |
528 | } |
529 | if ((null !== $this->resizedImage) && file_exists($this->resizedImage)) { |
530 | unlink($this->resizedImage); |
531 | } |
532 | } |
533 | |
534 | /** |
535 | * Parse the PNG image data |
536 | * |
537 | * @throws Exception |
538 | * @return void |
539 | */ |
540 | protected function parsePng() |
541 | { |
542 | // Define some PNG image-specific variables. |
543 | $PLTE = null; |
544 | $TRNS = null; |
545 | $maskIndex = null; |
546 | $mask = null; |
547 | |
548 | // Determine the PNG colorspace. |
549 | if ($this->colorMode == 'Gray') { |
550 | $numOfColors = 1; |
551 | $colorSpace = '/DeviceGray'; |
552 | } else if (stripos($this->colorMode, 'RGB') !== false) { |
553 | $numOfColors = 3; |
554 | $colorSpace = '/DeviceRGB'; |
555 | } else { |
556 | $numOfColors = 1; |
557 | $palIndex = $this->index + 1; |
558 | |
559 | // If the PNG is indexed, parse and read the palette and any transparencies that might exist. |
560 | if (strpos($this->imageData, 'PLTE') !== false) { |
561 | $lenByte = substr($this->imageData, (strpos($this->imageData, "PLTE") - 4), 4); |
562 | $palLength = $this->readInt($lenByte); |
563 | $PLTE = substr($this->imageData, (strpos($this->imageData, "PLTE") + 4), $palLength); |
564 | $mask = null; |
565 | |
566 | // If a transparency exists, parse it and set the mask accordingly, along with the palette. |
567 | if (strpos($this->imageData, 'tRNS') !== false) { |
568 | $lenByte = substr($this->imageData, (strpos($this->imageData, "tRNS") - 4), 4); |
569 | $TRNS = substr($this->imageData, (strpos($this->imageData, "tRNS") + 4), $this->readInt($lenByte)); |
570 | $maskIndex = strpos($TRNS, chr(0)); |
571 | $mask = " /Mask [" . $maskIndex . " " . $maskIndex . "]\n"; |
572 | } |
573 | } |
574 | |
575 | $this->colorTotal = imagecolorstotal($this->resource); |
576 | $colorSpace = "[/Indexed /DeviceRGB " . ($this->colorTotal - 1) . " " . $palIndex . " 0 R]"; |
577 | } |
578 | |
579 | // Parse header data, bits and color type |
580 | $lenByte = substr($this->imageData, (strpos($this->imageData, "IHDR") - 4), 4); |
581 | $header = substr($this->imageData, (strpos($this->imageData, "IHDR") + 4), $this->readInt($lenByte)); |
582 | $bits = ord(substr($header, 8, 1)); |
583 | $colorType = ord(substr($header, 9, 1)); |
584 | |
585 | // Make sure the PNG does not contain a true alpha channel. |
586 | if (($colorType >= 4) && (($bits == 8) || ($bits == 16))) { |
587 | throw new Exception('Error: PNG alpha channels are not supported. Only 8-bit transparent PNG images are supported.'); |
588 | } |
589 | |
590 | // Parse and set the PNG image data and data length. |
591 | $lenByte = substr($this->imageData, (strpos($this->imageData, "IDAT") - 4), 4); |
592 | $this->imageDataLength = $this->readInt($lenByte); |
593 | $IDAT = substr($this->imageData, (strpos($this->imageData, "IDAT") + 4), $this->imageDataLength); |
594 | |
595 | // Add the image to the objects array. |
596 | $this->objects[$this->index] = StreamObject::parse( |
597 | "{$this->index} 0 obj\n<<\n /Type /XObject\n /Subtype /Image\n /Width " . $this->width . |
598 | "\n /Height " . $this->height . "\n /ColorSpace {$colorSpace}\n /BitsPerComponent " . $bits . |
599 | "\n /Filter /FlateDecode\n /DecodeParms <</Predictor 15 /Colors {$numOfColors} /BitsPerComponent " . |
600 | $bits . " /Columns " . $this->width . ">>\n{$mask} /Length {$this->imageDataLength}\n>>\nstream\n{$IDAT}\nendstream\nendobj\n" |
601 | ); |
602 | |
603 | // If it exists, add the image palette to the objects array. |
604 | if ($PLTE != '') { |
605 | $this->objects[$palIndex] = StreamObject::parse( |
606 | "{$palIndex} 0 obj\n<<\n /Length " . $palLength . "\n>>\nstream\n{$PLTE}\nendstream\nendobj\n" |
607 | ); |
608 | $this->objects[$palIndex]->setPalette(true); |
609 | } |
610 | } |
611 | |
612 | /** |
613 | * Parse the JPG image data |
614 | * |
615 | * @throws Exception |
616 | * @return void |
617 | */ |
618 | protected function parseJpeg() |
619 | { |
620 | // Add the image to the objects array. |
621 | $colorMode = (strtolower($this->colorMode) == 'srgb') ? 'RGB' : $this->colorMode; |
622 | $colorSpace = ($this->colorMode == 'CMYK') ? "/DeviceCMYK\n /Decode [1 0 1 0 1 0 1 0]" : "/Device" . $colorMode; |
623 | $this->objects[$this->index] = StreamObject::parse( |
624 | "{$this->index} 0 obj\n<<\n /Type /XObject\n /Subtype /Image\n /Width " . $this->width . |
625 | "\n /Height " . $this->height . "\n /ColorSpace {$colorSpace}\n /BitsPerComponent 8\n " . |
626 | "/Filter /DCTDecode\n /Length {$this->imageDataLength}\n>>\nstream\n{$this->imageData}\nendstream\nendobj\n" |
627 | ); |
628 | } |
629 | |
630 | /** |
631 | * Create a new image resource based on the current image type |
632 | * of the image object. |
633 | * |
634 | * @return void |
635 | */ |
636 | protected function createResource() |
637 | { |
638 | if (null !== $this->stream) { |
639 | $this->resource = imagecreatefromstring($this->stream); |
640 | } else if (file_exists($this->fullpath)) { |
641 | switch ($this->mime) { |
642 | case 'image/gif': |
643 | $this->resource = imagecreatefromgif($this->fullpath); |
644 | break; |
645 | case 'image/png': |
646 | $this->resource = imagecreatefrompng($this->fullpath); |
647 | break; |
648 | case 'image/jpeg': |
649 | $this->resource = imagecreatefromjpeg($this->fullpath); |
650 | break; |
651 | } |
652 | } |
653 | } |
654 | |
655 | /** |
656 | * Method to convert the image to Jpg |
657 | * |
658 | * @param int $quality |
659 | * @return void |
660 | */ |
661 | public function convertToJpeg($quality = 70) |
662 | { |
663 | $this->convertedImage = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . $this->filename . '_' . time() . '.jpg'; |
664 | |
665 | $result = imagecreatetruecolor($this->width, $this->height); |
666 | imagecopyresampled( |
667 | $result, $this->resource, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height |
668 | ); |
669 | |
670 | $this->resource = $result; |
671 | $this->width = imagesx($this->resource); |
672 | $this->height = imagesy($this->resource); |
673 | |
674 | imagejpeg($this->resource, $this->convertedImage, (int)$quality); |
675 | } |
676 | |
677 | /** |
678 | * Method to convert the image from GIF to PNG. |
679 | * |
680 | * @return void |
681 | */ |
682 | protected function convertImage() |
683 | { |
684 | // Define the temp converted image. |
685 | $this->convertedImage = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . $this->filename . '_' . time() . '.png'; |
686 | |
687 | // Convert the GIF to PNG, save and clear the output buffer. |
688 | |
689 | $resource = (null !== $this->stream) ? |
690 | imagecreatefromstring($this->stream) : imagecreatefromgif($this->fullpath); |
691 | |
692 | imageinterlace($resource, 0); |
693 | imagepng($resource, $this->convertedImage); |
694 | |
695 | // Change the type of the image object to the new, |
696 | // requested image type. |
697 | $this->extension = 'png'; |
698 | $this->mime = 'image/png'; |
699 | |
700 | // Redefine the image object properties with the new values. |
701 | if (null !== $this->stream) { |
702 | $this->stream = file_get_contents($this->convertedImage); |
703 | } else { |
704 | $this->fullpath = $this->convertedImage; |
705 | } |
706 | $this->basename = basename($this->convertedImage); |
707 | $this->filename = basename($this->convertedImage, '.png'); |
708 | } |
709 | |
710 | /** |
711 | * Method to resize the image. |
712 | * |
713 | * @param array $resize |
714 | * @throws Exception |
715 | * @return void |
716 | */ |
717 | protected function resizeImage($resize) |
718 | { |
719 | // Define the temp resized image. |
720 | $this->resizedImage = realpath(sys_get_temp_dir()) . DIRECTORY_SEPARATOR . $this->filename . '_' . time() . '.' . $this->extension; |
721 | |
722 | // Get image properties. |
723 | if (null !== $this->stream) { |
724 | $imgSize = getimagesizefromstring($this->stream); |
725 | $resource = imagecreatefromstring($this->stream); |
726 | } else { |
727 | $imgSize = getimagesize($this->fullpath); |
728 | $resource = ($this->mime == 'image/png') ? |
729 | imagecreatefrompng($this->fullpath) : imagecreatefromjpeg($this->fullpath); |
730 | } |
731 | |
732 | $width = $imgSize[0]; |
733 | $height = $imgSize[1]; |
734 | $output = imagecreatetruecolor($resize['width'], $resize['height']); |
735 | |
736 | imagecopyresampled($output, $resource, 0, 0, 0, 0, $resize['width'], $resize['height'], $width, $height); |
737 | |
738 | if ($this->mime == 'image/png') { |
739 | imagepng($output, $this->resizedImage, 1); |
740 | $this->filename = basename($this->resizedImage, '.png'); |
741 | } else { |
742 | imagejpeg($output, $this->resizedImage, 90); |
743 | $this->filename = basename($this->resizedImage, '.jpg'); |
744 | } |
745 | |
746 | $this->basename = basename($this->resizedImage); |
747 | |
748 | if (null !== $this->stream) { |
749 | $this->stream = file_get_contents($this->resizedImage); |
750 | } else { |
751 | $this->fullpath = $this->resizedImage; |
752 | } |
753 | } |
754 | |
755 | /** |
756 | * Method to read an unsigned integer. |
757 | * |
758 | * @param string $data |
759 | * @return int |
760 | */ |
761 | protected function readInt($data) |
762 | { |
763 | $ary = unpack('Nlength', $data); |
764 | return $ary['length']; |
765 | } |
766 | |
767 | } |