Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
91.82% |
247 / 269 |
|
78.57% |
33 / 42 |
CRAP | |
0.00% |
0 / 1 |
Imagick | |
91.82% |
247 / 269 |
|
78.57% |
33 / 42 |
150.72 | |
0.00% |
0 / 1 |
createResource | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
load | |
81.48% |
22 / 27 |
|
0.00% |
0 / 1 |
17.63 | |||
loadFromString | |
65.00% |
13 / 20 |
|
0.00% |
0 / 1 |
16.19 | |||
create | |
92.86% |
13 / 14 |
|
0.00% |
0 / 1 |
7.02 | |||
createIndex | |
93.75% |
15 / 16 |
|
0.00% |
0 / 1 |
7.01 | |||
addImage | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
hasImages | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImages | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
rebuildImages | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setResolution | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
setImageColorspace | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setCompression | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setImageFilter | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
setImageBlur | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getNumberOfImages | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getCompression | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImageFilter | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImageBlur | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
resizeToWidth | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
resizeToHeight | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
resize | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
scale | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
resizeImage | |
72.73% |
8 / 11 |
|
0.00% |
0 / 1 |
5.51 | |||
crop | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
cropThumb | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
6 | |||
cropImage | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
3.01 | |||
cropThumbnailImage | |
90.00% |
9 / 10 |
|
0.00% |
0 / 1 |
3.01 | |||
rotate | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
flip | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
flop | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
adjust | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
draw | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
effect | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
filter | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
layer | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
type | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
convert | |
90.00% |
18 / 20 |
|
0.00% |
0 / 1 |
9.08 | |||
writeToFile | |
90.91% |
10 / 11 |
|
0.00% |
0 / 1 |
9.06 | |||
outputToHttp | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
10 | |||
destroy | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
4 | |||
createColor | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
__toString | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 |
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\Image\Adapter; |
15 | |
16 | use Pop\Image\Adjust; |
17 | use Pop\Image\Color; |
18 | use Pop\Image\Draw; |
19 | use Pop\Image\Effect; |
20 | use Pop\Image\Filter; |
21 | use Pop\Image\Layer; |
22 | use Pop\Image\Type; |
23 | |
24 | /** |
25 | * Imagick adapter class |
26 | * |
27 | * @category Pop |
28 | * @package Pop\Image |
29 | * @author Nick Sagona, III <dev@nolainteractive.com> |
30 | * @copyright Copyright (c) 2009-2023 NOLA Interactive, LLC. (http://www.nolainteractive.com) |
31 | * @license http://www.popphp.org/license New BSD License |
32 | * @version 3.4.0 |
33 | */ |
34 | class Imagick extends AbstractAdapter |
35 | { |
36 | |
37 | /** |
38 | * Image compression |
39 | * @var int |
40 | */ |
41 | protected $compression = null; |
42 | |
43 | /** |
44 | * Image filter |
45 | * @var int |
46 | */ |
47 | protected $imageFilter = \Imagick::FILTER_LANCZOS; |
48 | |
49 | /** |
50 | * Image blur |
51 | * @var float |
52 | */ |
53 | protected $imageBlur = 1; |
54 | |
55 | /** |
56 | * Create the image resource |
57 | * |
58 | * @return void |
59 | */ |
60 | public function createResource() |
61 | { |
62 | $this->resource = new \Imagick(); |
63 | } |
64 | |
65 | /** |
66 | * Load the image resource from the existing image file |
67 | * |
68 | * @param string $name |
69 | * @throws Exception |
70 | * @return Imagick |
71 | */ |
72 | public function load($name = null) |
73 | { |
74 | $filename = null; |
75 | if (null !== $name) { |
76 | $filename = ((strpos($name, '[') !== false) && (strpos($name, ']') !== false)) ? |
77 | substr($name, 0, strpos($name, '[')) : $name; |
78 | $this->name = $name; |
79 | } |
80 | |
81 | if ((null === $this->name) || ((null !== $filename) && !file_exists($filename))) { |
82 | throw new Exception('Error: The image file has not been passed to the image adapter'); |
83 | } |
84 | |
85 | if (null !== $this->resource) { |
86 | $this->resource->readImage($this->name); |
87 | } else { |
88 | $this->resource = new \Imagick($this->name); |
89 | } |
90 | |
91 | $this->width = $this->resource->getImageWidth(); |
92 | $this->height = $this->resource->getImageHeight(); |
93 | |
94 | switch ($this->resource->getImageColorspace()) { |
95 | case \Imagick::COLORSPACE_GRAY: |
96 | $this->colorspace = self::IMAGE_GRAY; |
97 | break; |
98 | case \Imagick::COLORSPACE_RGB: |
99 | case \Imagick::COLORSPACE_SRGB: |
100 | $this->colorspace = self::IMAGE_RGB; |
101 | break; |
102 | case \Imagick::COLORSPACE_CMYK: |
103 | $this->colorspace = self::IMAGE_CMYK; |
104 | break; |
105 | } |
106 | |
107 | $this->format = strtolower($this->resource->getImageFormat()); |
108 | if ($this->resource->getImageColors() < 256) { |
109 | $this->indexed = true; |
110 | } |
111 | |
112 | if ((strpos($this->format, 'jp') !== false) && function_exists('exif_read_data')) { |
113 | $exif = @exif_read_data($this->name); |
114 | if ($exif !== false) { |
115 | $this->exif = $exif; |
116 | } |
117 | } |
118 | |
119 | return $this; |
120 | } |
121 | |
122 | /** |
123 | * Load the image resource from data |
124 | * |
125 | * @param string $data |
126 | * @param string $name |
127 | * @return Imagick |
128 | */ |
129 | public function loadFromString($data, $name = null) |
130 | { |
131 | if (null === $this->resource) { |
132 | $this->resource = new \Imagick(); |
133 | } |
134 | $this->resource->readImageBlob($data); |
135 | |
136 | if (null !== $name) { |
137 | $this->name = $name; |
138 | } |
139 | |
140 | switch ($this->resource->getImageColorspace()) { |
141 | case \Imagick::COLORSPACE_GRAY: |
142 | $this->colorspace = self::IMAGE_GRAY; |
143 | break; |
144 | case \Imagick::COLORSPACE_RGB: |
145 | case \Imagick::COLORSPACE_SRGB: |
146 | $this->colorspace = self::IMAGE_RGB; |
147 | break; |
148 | case \Imagick::COLORSPACE_CMYK: |
149 | $this->colorspace = self::IMAGE_CMYK; |
150 | break; |
151 | } |
152 | |
153 | $this->format = strtolower($this->resource->getImageFormat()); |
154 | if ($this->resource->getImageColors() < 256) { |
155 | $this->indexed = true; |
156 | } |
157 | |
158 | if ((strpos($this->format, 'jp') !== false) && function_exists('exif_read_data')) { |
159 | $exif = @exif_read_data('data://image/jpeg;base64,' . base64_encode($data)); |
160 | if ($exif !== false) { |
161 | $this->exif = $exif; |
162 | } |
163 | } |
164 | |
165 | return $this; |
166 | } |
167 | |
168 | /** |
169 | * Create a new image resource |
170 | * |
171 | * @param int $width |
172 | * @param int $height |
173 | * @param string $name |
174 | * @return Imagick |
175 | */ |
176 | public function create($width = null, $height = null, $name = null) |
177 | { |
178 | if ((null !== $width) && (null !== $height)) { |
179 | $this->width = $width; |
180 | $this->height = $height; |
181 | } |
182 | |
183 | if (null !== $name) { |
184 | $this->name = $name; |
185 | } |
186 | |
187 | if (null === $this->resource) { |
188 | $this->resource = new \Imagick(); |
189 | } |
190 | |
191 | $this->resource->newImage($this->width, $this->height, new \ImagickPixel('white')); |
192 | |
193 | if (null !== $this->name) { |
194 | $extension = strtolower(substr($this->name, (strrpos($this->name, '.') + 1))); |
195 | if (!empty($extension)) { |
196 | $this->resource->setImageFormat($extension); |
197 | $this->format = $extension; |
198 | } |
199 | } |
200 | |
201 | return $this; |
202 | } |
203 | |
204 | /** |
205 | * Create a new image resource |
206 | * |
207 | * @param int $width |
208 | * @param int $height |
209 | * @param string $name |
210 | * @return Imagick |
211 | */ |
212 | public function createIndex($width = null, $height = null, $name = null) |
213 | { |
214 | if ((null !== $width) && (null !== $height)) { |
215 | $this->width = $width; |
216 | $this->height = $height; |
217 | } |
218 | |
219 | if (null !== $name) { |
220 | $this->name = $name; |
221 | } |
222 | |
223 | if (null === $this->resource) { |
224 | $this->resource = new \Imagick(); |
225 | } |
226 | |
227 | $this->resource->newImage($this->width, $this->height, new \ImagickPixel('white')); |
228 | |
229 | if (null !== $this->name) { |
230 | $extension = strtolower(substr($this->name, (strrpos($this->name, '.') + 1))); |
231 | if (!empty($extension)) { |
232 | $this->resource->setImageFormat($extension); |
233 | $this->format = $extension; |
234 | } |
235 | } |
236 | |
237 | $this->resource->setImageType(\Imagick::IMGTYPE_PALETTE); |
238 | $this->indexed = true; |
239 | |
240 | return $this; |
241 | } |
242 | |
243 | /** |
244 | * Add image to the image resource |
245 | * |
246 | * @param mixed $image |
247 | * @param int $delay |
248 | * @return Imagick |
249 | */ |
250 | public function addImage($image, $delay = null) |
251 | { |
252 | if (!($image instanceof \Imagick)) { |
253 | $image = new \Imagick($image); |
254 | } |
255 | if (null !== $delay) { |
256 | $image->setImageDelay($delay); |
257 | } |
258 | $this->resource->addImage($image); |
259 | return $this; |
260 | } |
261 | |
262 | /** |
263 | * Does image have images |
264 | * |
265 | * @return boolean |
266 | */ |
267 | public function hasImages() |
268 | { |
269 | return ($this->resource->getNumberImages() > 0); |
270 | } |
271 | |
272 | /** |
273 | * Get images |
274 | * |
275 | * @return array |
276 | */ |
277 | public function getImages() |
278 | { |
279 | return $this->resource->coalesceImages(); |
280 | } |
281 | |
282 | /** |
283 | * Get images |
284 | * |
285 | * @param \Imagick $images |
286 | * @return Imagick |
287 | */ |
288 | public function rebuildImages(\Imagick $images) |
289 | { |
290 | $this->resource = $images->deconstructImages(); |
291 | return $this; |
292 | } |
293 | |
294 | /** |
295 | * Set the image resolution |
296 | * |
297 | * @param int $x |
298 | * @param int $y |
299 | * @return Imagick |
300 | */ |
301 | public function setResolution($x, $y = null) |
302 | { |
303 | if (null === $y) { |
304 | $y = $x; |
305 | } |
306 | $this->resource->setResolution($x, $y); |
307 | return $this; |
308 | } |
309 | |
310 | /** |
311 | * Set the image colorspace |
312 | * |
313 | * @param int $colorspace |
314 | * @return Imagick |
315 | */ |
316 | public function setImageColorspace($colorspace) |
317 | { |
318 | $this->resource->setImageColorspace($colorspace); |
319 | return $this; |
320 | } |
321 | |
322 | /** |
323 | * Set the image compression |
324 | * |
325 | * @param int $compression |
326 | * @return Imagick |
327 | */ |
328 | public function setCompression($compression) |
329 | { |
330 | $this->compression = $compression; |
331 | return $this; |
332 | } |
333 | |
334 | /** |
335 | * Set the image filter |
336 | * |
337 | * @param int $filter |
338 | * @return Imagick |
339 | */ |
340 | public function setImageFilter($filter) |
341 | { |
342 | $this->imageFilter = $filter; |
343 | return $this; |
344 | } |
345 | |
346 | /** |
347 | * Set the image blur |
348 | * |
349 | * @param float $blur |
350 | * @return Imagick |
351 | */ |
352 | public function setImageBlur($blur) |
353 | { |
354 | $this->imageBlur = $blur; |
355 | return $this; |
356 | } |
357 | |
358 | /** |
359 | * Get number of images |
360 | * |
361 | * @return int |
362 | */ |
363 | public function getNumberOfImages() |
364 | { |
365 | return $this->resource->getNumberImages(); |
366 | } |
367 | |
368 | /** |
369 | * Get the image compression |
370 | * |
371 | * @return int |
372 | */ |
373 | public function getCompression() |
374 | { |
375 | return $this->compression; |
376 | } |
377 | |
378 | /** |
379 | * Get the image filter |
380 | * |
381 | * @return int |
382 | */ |
383 | public function getImageFilter() |
384 | { |
385 | return $this->imageFilter; |
386 | } |
387 | |
388 | /** |
389 | * Get the image blur |
390 | * |
391 | * @return float |
392 | */ |
393 | public function getImageBlur() |
394 | { |
395 | return $this->imageBlur; |
396 | } |
397 | |
398 | /** |
399 | * Resize the image object to the width parameter passed |
400 | * |
401 | * @param int $w |
402 | * @return Imagick |
403 | */ |
404 | public function resizeToWidth($w) |
405 | { |
406 | $scale = $w / $this->width; |
407 | $this->width = $w; |
408 | $this->height = round($this->height * $scale); |
409 | |
410 | return $this->resizeImage($this->width, $this->height, $this->imageFilter, $this->imageBlur); |
411 | } |
412 | |
413 | /** |
414 | * Resize the image object to the height parameter passed |
415 | * |
416 | * @param int $h |
417 | * @return Imagick |
418 | */ |
419 | public function resizeToHeight($h) |
420 | { |
421 | $scale = $h / $this->height; |
422 | $this->height = $h; |
423 | $this->width = round($this->width * $scale); |
424 | |
425 | return $this->resizeImage($this->width, $this->height, $this->imageFilter, $this->imageBlur); |
426 | } |
427 | |
428 | /** |
429 | * Resize the image object, allowing for the largest dimension |
430 | * to be scaled to the value of the $px argument. |
431 | * |
432 | * @param int $px |
433 | * @return Imagick |
434 | */ |
435 | public function resize($px) |
436 | { |
437 | $scale = ($this->width > $this->height) ? ($px / $this->width) : ($px / $this->height); |
438 | $this->width = round($this->width * $scale); |
439 | $this->height = round($this->height * $scale); |
440 | |
441 | return $this->resizeImage($this->width, $this->height, $this->imageFilter, $this->imageBlur); |
442 | } |
443 | |
444 | /** |
445 | * Scale the image object, allowing for the dimensions to be scaled |
446 | * proportionally to the value of the $scl argument. |
447 | * |
448 | * @param float $scale |
449 | * @return Imagick |
450 | */ |
451 | public function scale($scale) |
452 | { |
453 | $this->width = round($this->width * $scale); |
454 | $this->height = round($this->height * $scale); |
455 | |
456 | return $this->resizeImage($this->width, $this->height, $this->imageFilter, $this->imageBlur); |
457 | } |
458 | |
459 | /** |
460 | * Resize image, checking for multiple frames |
461 | * |
462 | * @param int $width |
463 | * @param int $height |
464 | * @param int $filter |
465 | * @param int $blur |
466 | * @return Imagick |
467 | */ |
468 | public function resizeImage($width, $height, $filter = null, $blur = null) |
469 | { |
470 | if (null === $filter) { |
471 | $filter = $this->imageFilter; |
472 | } |
473 | if (null === $blur) { |
474 | $blur = $this->imageBlur; |
475 | } |
476 | if ($this->resource->getNumberImages() > 0) { |
477 | $frames = $this->resource->coalesceImages(); |
478 | foreach ($frames as $frame) { |
479 | $frame->resizeImage($width, $height, $filter, $blur); |
480 | } |
481 | $this->resource = $frames->deconstructImages(); |
482 | } else { |
483 | $this->resource->resizeImage($width, $height, $filter, $blur); |
484 | } |
485 | |
486 | return $this; |
487 | } |
488 | |
489 | /** |
490 | * Crop the image object to a image whose dimensions are based on the |
491 | * value of the $wid and $hgt argument. The optional $x and $y arguments |
492 | * allow for the adjustment of the crop to select a certain area of the |
493 | * image to be cropped. |
494 | * |
495 | * @param int $w |
496 | * @param int $h |
497 | * @param int $x |
498 | * @param int $y |
499 | * @return Imagick |
500 | */ |
501 | public function crop($w, $h, $x = 0, $y = 0) |
502 | { |
503 | $this->width = $w; |
504 | $this->height = $h; |
505 | return $this->cropImage($this->width, $this->height, $x, $y); |
506 | } |
507 | |
508 | /** |
509 | * Crop the image object to a square image whose dimensions are based on the |
510 | * value of the $px argument. The optional $offset argument allows for the |
511 | * adjustment of the crop to select a certain area of the image to be cropped. |
512 | * |
513 | * @param int $px |
514 | * @param int $offset |
515 | * @return Imagick |
516 | */ |
517 | public function cropThumb($px, $offset = null) |
518 | { |
519 | $xOffset = 0; |
520 | $yOffset = 0; |
521 | |
522 | if (null !== $offset) { |
523 | if ($this->width > $this->height) { |
524 | $xOffset = $offset; |
525 | $yOffset = 0; |
526 | } else if ($this->width < $this->height) { |
527 | $xOffset = 0; |
528 | $yOffset = $offset; |
529 | } |
530 | } |
531 | |
532 | $scale = ($this->width > $this->height) ? ($px / $this->height) : ($px / $this->width); |
533 | |
534 | $wid = round($this->width * $scale); |
535 | $hgt = round($this->height * $scale); |
536 | |
537 | // Create a new image output resource. |
538 | if (null !== $offset) { |
539 | $this->resizeImage($wid, $hgt, $this->imageFilter, $this->imageBlur); |
540 | $this->cropImage($px, $px, $xOffset, $yOffset); |
541 | } else { |
542 | $this->cropThumbnailImage($px, $px); |
543 | } |
544 | |
545 | $this->width = $px; |
546 | $this->height = $px; |
547 | return $this; |
548 | } |
549 | |
550 | /** |
551 | * Crop image, checking for multiple frames |
552 | * |
553 | * @param int $width |
554 | * @param int $height |
555 | * @param int $x |
556 | * @param int $y |
557 | * @return Imagick |
558 | */ |
559 | public function cropImage($width, $height, $x, $y) |
560 | { |
561 | if ($this->resource->getNumberImages() > 0) { |
562 | $frames = $this->resource->coalesceImages(); |
563 | foreach ($frames as $frame) { |
564 | $frame->setImageBackgroundColor('none'); |
565 | $frame->cropImage($width, $height, $x, $y); |
566 | $frame->thumbnailImage($width, $height); |
567 | $frame->setImagePage($width, $height, 0, 0); |
568 | } |
569 | $this->resource = $frames->deconstructImages(); |
570 | $this->resource->resizeImage($width, $height, $this->imageFilter, $this->imageBlur); |
571 | } else { |
572 | $this->resource->cropImage($width, $height, $x, $y); |
573 | } |
574 | |
575 | return $this; |
576 | } |
577 | |
578 | /** |
579 | * Crop image, checking for multiple frames |
580 | * |
581 | * @param int $width |
582 | * @param int $height |
583 | * @return Imagick |
584 | */ |
585 | public function cropThumbnailImage($width, $height) |
586 | { |
587 | if ($this->resource->getNumberImages() > 0) { |
588 | $frames = $this->resource->coalesceImages(); |
589 | foreach ($frames as $frame) { |
590 | $frame->setImageBackgroundColor('none'); |
591 | $frame->cropThumbnailImage($width, $height); |
592 | $frame->thumbnailImage($width, $height); |
593 | $frame->setImagePage($width, $height, 0, 0); |
594 | } |
595 | $this->resource = $frames->deconstructImages(); |
596 | } else { |
597 | $this->resource->cropThumbnailImage($width, $height); |
598 | } |
599 | |
600 | return $this; |
601 | } |
602 | |
603 | /** |
604 | * Rotate the image object |
605 | * |
606 | * @param int $degrees |
607 | * @param Color\ColorInterface $bgColor |
608 | * @return Imagick |
609 | */ |
610 | public function rotate($degrees, Color\ColorInterface $bgColor = null) |
611 | { |
612 | $this->resource->rotateImage($this->createColor($bgColor), $degrees); |
613 | $this->width = $this->resource->getImageWidth(); |
614 | $this->height = $this->resource->getImageHeight(); |
615 | return $this; |
616 | } |
617 | |
618 | /** |
619 | * Method to flip the image over the x-axis |
620 | * |
621 | * @return Imagick |
622 | */ |
623 | public function flip() |
624 | { |
625 | $this->resource->flipImage(); |
626 | return $this; |
627 | } |
628 | |
629 | /** |
630 | * Method to flip the image over the y-axis |
631 | * |
632 | * @return Imagick |
633 | */ |
634 | public function flop() |
635 | { |
636 | $this->resource->flopImage(); |
637 | return $this; |
638 | } |
639 | |
640 | /** |
641 | * Get the image adjust object |
642 | * |
643 | * @return Adjust\AdjustInterface |
644 | */ |
645 | public function adjust() |
646 | { |
647 | if (null === $this->adjust) { |
648 | $this->adjust = new Adjust\Imagick($this); |
649 | } |
650 | if (null === $this->adjust->getImage()) { |
651 | $this->adjust->setImage($this); |
652 | } |
653 | |
654 | return $this->adjust; |
655 | } |
656 | |
657 | /** |
658 | * Get the image draw object |
659 | * |
660 | * @return Draw\DrawInterface |
661 | */ |
662 | public function draw() |
663 | { |
664 | if (null === $this->draw) { |
665 | $this->draw = new Draw\Imagick($this); |
666 | } |
667 | if (null === $this->draw->getImage()) { |
668 | $this->draw->setImage($this); |
669 | } |
670 | return $this->draw; |
671 | } |
672 | |
673 | /** |
674 | * Get the image effect object |
675 | * |
676 | * @return Effect\EffectInterface |
677 | */ |
678 | public function effect() |
679 | { |
680 | if (null === $this->effect) { |
681 | $this->effect = new Effect\Imagick($this); |
682 | } |
683 | if (null === $this->effect->getImage()) { |
684 | $this->effect->setImage($this); |
685 | } |
686 | return $this->effect; |
687 | } |
688 | |
689 | /** |
690 | * Get the image filter object |
691 | * |
692 | * @return Filter\FilterInterface |
693 | */ |
694 | public function filter() |
695 | { |
696 | if (null === $this->filter) { |
697 | $this->filter = new Filter\Imagick($this); |
698 | } |
699 | if (null === $this->filter->getImage()) { |
700 | $this->filter->setImage($this); |
701 | } |
702 | return $this->filter; |
703 | } |
704 | |
705 | /** |
706 | * Get the image layer object |
707 | * |
708 | * @return Layer\LayerInterface |
709 | */ |
710 | public function layer() |
711 | { |
712 | if (null === $this->layer) { |
713 | $this->layer = new Layer\Imagick($this); |
714 | } |
715 | if (null === $this->layer->getImage()) { |
716 | $this->layer->setImage($this); |
717 | } |
718 | return $this->layer; |
719 | } |
720 | |
721 | /** |
722 | * Get the image type object |
723 | * |
724 | * @return Type\TypeInterface |
725 | */ |
726 | public function type() |
727 | { |
728 | if (null === $this->type) { |
729 | $this->type = new Type\Imagick($this); |
730 | } |
731 | if (null === $this->type->getImage()) { |
732 | $this->type->setImage($this); |
733 | } |
734 | return $this->type; |
735 | } |
736 | |
737 | /** |
738 | * Convert the image object to another format |
739 | * |
740 | * @param string $to |
741 | * @return Imagick |
742 | */ |
743 | public function convert($to) |
744 | { |
745 | $to = strtolower($to); |
746 | $old = strtolower($this->format); |
747 | |
748 | if (($old == 'psd') || ($old == 'tif') || ($old == 'tiff')) { |
749 | $this->resource->mergeImageLayers(\Imagick::LAYERMETHOD_FLATTEN); |
750 | } |
751 | |
752 | $this->resource->setImageFormat($to); |
753 | |
754 | switch ($to) { |
755 | case 'jpg': |
756 | case 'jpeg': |
757 | $this->format = 'jpg'; |
758 | $this->indexed = false; |
759 | break; |
760 | case 'png': |
761 | $this->format = 'png'; |
762 | break; |
763 | case 'gif': |
764 | $this->format = 'gif'; |
765 | $this->indexed = true; |
766 | break; |
767 | default: |
768 | $this->format = $to; |
769 | } |
770 | |
771 | return $this; |
772 | } |
773 | |
774 | /** |
775 | * Write the image object to a file on disk |
776 | * |
777 | * @param string $to |
778 | * @param int $quality |
779 | * @throws Exception |
780 | * @return void |
781 | */ |
782 | public function writeToFile($to = null, $quality = 100) |
783 | { |
784 | if ((null === $this->resource) || ((null !== $this->resource) && ($this->resource->count() == 0))) { |
785 | throw new Exception('Error: An image resource has not been created or loaded'); |
786 | } |
787 | |
788 | if (null !== $this->compression) { |
789 | $this->resource->setImageCompression($this->compression); |
790 | } |
791 | |
792 | if (((int)$quality < 0) || ((int)$quality > 100)) { |
793 | throw new \OutOfRangeException('Error: The quality parameter must be between 0 and 100'); |
794 | } |
795 | |
796 | $this->resource->setImageCompressionQuality($quality); |
797 | |
798 | if (null === $to) { |
799 | $to = (null !== $this->name) ? basename($this->name) : 'pop-image.' . $this->format; |
800 | } else { |
801 | $this->name = $to; |
802 | } |
803 | |
804 | $this->resource->writeImage($to); |
805 | } |
806 | |
807 | /** |
808 | * Output the image object directly to HTTP |
809 | * |
810 | * @param int $quality |
811 | * @param string $to |
812 | * @param boolean $download |
813 | * @param boolean $sendHeaders |
814 | * @param array $headers |
815 | * @throws Exception |
816 | * @return void |
817 | */ |
818 | public function outputToHttp($quality = 100, $to = null, $download = false, $sendHeaders = true, array $headers = []) |
819 | { |
820 | if ((null === $this->resource) || ((null !== $this->resource) && ($this->resource->count() == 0))) { |
821 | throw new Exception('Error: An image resource has not been created or loaded'); |
822 | } |
823 | |
824 | if (((int)$quality < 0) || ((int)$quality > 100)) { |
825 | throw new \OutOfRangeException('Error: The quality parameter must be between 0 and 100'); |
826 | } |
827 | |
828 | if (null !== $this->compression) { |
829 | $this->resource->setImageCompression($this->compression); |
830 | } |
831 | |
832 | $this->resource->setImageCompressionQuality($quality); |
833 | |
834 | if (null === $to) { |
835 | $to = (null !== $this->name) ? basename($this->name) : 'pop-image.' . strtolower($this->format); |
836 | } |
837 | |
838 | $this->sendHeaders($to, $download, $headers); |
839 | echo ($this->resource->getNumberImages() > 0) ? $this->resource->getImagesBlob() : $this->resource; |
840 | } |
841 | |
842 | /** |
843 | * Destroy the image object and the related image file directly |
844 | * |
845 | * @param boolean $delete |
846 | * @return void |
847 | */ |
848 | public function destroy($delete = false) |
849 | { |
850 | if (null !== $this->resource) { |
851 | $this->resource->clear(); |
852 | $this->resource->destroy(); |
853 | } |
854 | |
855 | $this->resource = null; |
856 | clearstatcache(); |
857 | |
858 | // If the $delete flag is passed, delete the image file. |
859 | if (($delete) && file_exists($this->name)) { |
860 | unlink($this->name); |
861 | } |
862 | } |
863 | |
864 | /** |
865 | * Create and return a color. |
866 | * |
867 | * @param Color\ColorInterface $color |
868 | * @param int $alpha |
869 | * @return \ImagickPixel |
870 | */ |
871 | public function createColor(Color\ColorInterface $color = null, $alpha = 100) |
872 | { |
873 | if (null === $color) { |
874 | $color = new Color\Rgb(0, 0, 0); |
875 | } |
876 | |
877 | if (!($color instanceof Color\Rgb)) { |
878 | $color = $color->toRgb(); |
879 | } |
880 | |
881 | return ((int)$alpha < 100) ? |
882 | new \ImagickPixel('rgba(' . $color . ',' . (int)$alpha . ')') : new \ImagickPixel('rgb(' . $color . ')'); |
883 | } |
884 | |
885 | /** |
886 | * Output the image |
887 | * |
888 | * @return string |
889 | */ |
890 | public function __toString() |
891 | { |
892 | $this->sendHeaders(); |
893 | echo ($this->resource->getNumberImages() > 0) ? $this->resource->getImagesBlob() : $this->resource; |
894 | return ''; |
895 | } |
896 | |
897 | } |