GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

ImagemagickDriver::rotate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * This file is part of the O2System Framework package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @author         Steeve Andrian Salim
9
 * @copyright      Copyright (c) Steeve Andrian Salim
10
 */
11
12
// ------------------------------------------------------------------------
13
14
namespace O2System\Image\Drivers;
15
16
// ------------------------------------------------------------------------
17
18
use O2System\Image\Abstracts\AbstractDriver;
19
use O2System\Image\Abstracts\AbstractWatermark;
20
use O2System\Image\Dimension;
21
use O2System\Image\Watermark\Overlay;
22
use O2System\Image\Watermark\Text;
23
use O2System\Spl\Exceptions\Logic\BadFunctionCall\BadPhpExtensionCallException;
24
25
/**
26
 * Class ImagemagickDriver
27
 *
28
 * @package O2System\Image\Drivers
29
 */
30
class ImagemagickDriver extends AbstractDriver
31
{
32
    /**
33
     * ImagemagickDriver::__construct
34
     *
35
     * @throws \O2System\Spl\Exceptions\Logic\BadFunctionCall\BadPhpExtensionCallException
36
     */
37
    public function __construct()
38
    {
39
        if ( ! class_exists('Imagick', false)) {
40
            throw new BadPhpExtensionCallException('IMAGE_E_PHP_EXTENSION', 0, ['imagick']);
41
        }
42
    }
43
44
    // ------------------------------------------------------------------------
45
46
    /**
47
     * ImagemagickDriver::__destruct
48
     */
49
    public function __destruct()
50
    {
51
        if (is_object($this->sourceImageResource)) {
52
            $this->sourceImageResource->destroy();
53
        }
54
55
        if (is_object($this->resampleImageResource)) {
56
            $this->resampleImageResource->destroy();
57
        }
58
    }
59
60
    // ------------------------------------------------------------------------
61
62
    /**
63
     * ImagemagickDriver::createFromString
64
     *
65
     * Create an image resource from image string.
66
     *
67
     * @param string $imageString Image string.
68
     *
69
     * @return bool
70
     * @throws \ImagickException
71
     */
72
    public function createFromString($imageString)
73
    {
74
        $this->sourceImageResource = new \Imagick();
75
76
        try {
77
78
            return $this->sourceImageResource->readImageBlob($imageString);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->sourceImag...ImageBlob($imageString) returns the type boolean which is incompatible with the return type mandated by O2System\Image\Abstracts...ver::createFromString() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
79
80
        } catch (\ImagickException $e) {
81
82
            $this->errors[ $e->getCode() ] = $e->getMessage();
83
84
        }
85
86
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by O2System\Image\Abstracts...ver::createFromString() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
87
    }
88
89
    // ------------------------------------------------------------------------
90
91
    /**
92
     * ImagemagickDriver::rotate
93
     *
94
     * Rotate an image with a given angle.
95
     *
96
     * @param float $degrees Image rotation degrees.
97
     *
98
     * @return bool
99
     */
100
    public function rotate($degrees)
101
    {
102
        $resampleImageResource =& $this->getResampleImageResource();
103
104
        return $resampleImageResource->rotateImage('#000000', $degrees);
105
    }
106
107
    // ------------------------------------------------------------------------
108
109
    /**
110
     * ImagemagickDriver::flip
111
     *
112
     * Flip an image with a given axis.
113
     *
114
     * @param int $axis Flip axis.
115
     *
116
     * @return bool
117
     */
118
    public function flip($axis)
119
    {
120
        $gdAxis = [
121
            1 => IMG_FLIP_HORIZONTAL,
122
            2 => IMG_FLIP_VERTICAL,
123
            3 => IMG_FLIP_BOTH,
124
        ];
125
126
        if (array_key_exists($axis, $gdAxis)) {
127
            $resampleImageResource =& $this->getResampleImageResource();
128
129
            try {
130
131
                switch ($axis) {
132
                    case 1:
133
                        $resampleImageResource->flopImage();
134
                        break;
135
                    case 2:
136
                        $resampleImageResource->flipImage();
137
                        break;
138
                    case 3:
139
                        $resampleImageResource->flopImage();
140
                        $resampleImageResource->flipImage();
141
                        break;
142
                }
143
144
                return true;
0 ignored issues
show
Bug Best Practice introduced by
The expression return true returns the type true which is incompatible with the return type mandated by O2System\Image\Abstracts\AbstractDriver::flip() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
145
146
            } catch (\ImagickException $e) {
147
                $this->errors[ $e->getCode() ] = $e->getMessage();
148
            }
149
        }
150
151
        return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by O2System\Image\Abstracts\AbstractDriver::flip() of void.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
152
    }
153
154
    // ------------------------------------------------------------------------
155
156
    /**
157
     * ImagemagickDriver::resize
158
     *
159
     * Resize an image using the given new width and height.
160
     *
161
     * @param bool $crop Perform auto crop or not
162
     *
163
     * @return bool
164
     */
165
    public function resize($crop = false)
166
    {
167
        if ($crop) {
168
            return $this->resizeCrop();
169
        } else {
170
            $sourceDimension = $this->sourceImageFile->getDimension();
171
            $resampleDimension = $this->resampleImageFile->getDimension();
172
173
            if (($sourceDimension->getWidth() <= $resampleDimension->getWidth()) && ($sourceDimension->getHeight() <= $resampleDimension->getHeight())) {
174
                return true;
175
            } //no resizing needed
176
177
            //try max width first...
178
            $resizeRatio = $resampleDimension->getWidth() / $sourceDimension->getWidth();
179
            $resizeWidth = $resampleDimension->getWidth();
180
            $resizeHeight = $sourceDimension->getHeight() * $resizeRatio;
181
182
            //if that didn't work
183
            if ($resizeHeight > $resampleDimension->getHeight()) {
184
                $resizeRatio = $resampleDimension->getHeight() / $sourceDimension->getHeight();
185
                $resizeHeight = $resampleDimension->getHeight();
186
                $resizeWidth = $sourceDimension->getWidth() * $resizeRatio;
187
            }
188
189
            $resampleImageResource =& $this->getResampleImageResource();
190
191
            return $resampleImageResource->resizeImage(
192
                $resizeWidth,
193
                $resizeHeight,
194
                \Imagick::FILTER_CATROM, 0.9, true);
195
        }
196
    }
197
198
    // ------------------------------------------------------------------------
199
200
    /**
201
     * ImagemagickDriver::resizeCrop
202
     *
203
     * @return bool
204
     */
205
    public function resizeCrop()
206
    {
207
        $sourceDimension = $this->sourceImageFile->getDimension();
208
        $resampleDimension = $this->resampleImageFile->getDimension();
209
210
        //try max width first...
211
        $resizeRatio = $resampleDimension->getWidth() / $sourceDimension->getWidth();
212
        $resizeWidth = $resampleDimension->getWidth();
213
        $resizeHeight = $sourceDimension->getHeight() * $resizeRatio;
214
215
        //if that didn't work
216
        if ($resizeHeight > $resampleDimension->getHeight()) {
217
            $resizeRatio = $resampleDimension->getHeight() / $sourceDimension->getHeight();
218
            $resizeHeight = $resampleDimension->getHeight();
219
            $resizeWidth = $sourceDimension->getWidth() * $resizeRatio;
220
        }
221
222
        $resampleImageResource =& $this->getResampleImageResource();
223
224
        if ($resampleDimension->getOrientation() === 'SQUARE') {
225
            if ($resampleImageResource->resizeImage($resizeWidth, $resizeHeight, \Imagick::FILTER_LANCZOS, 0.9,
226
                true)
227
            ) {
228
                $resampleAxis = new Dimension\Axis(
229
                    ($resizeWidth - $resampleDimension->getWidth()) / 2,
230
                    ($resizeHeight - $resampleDimension->getWidth()) / 2
231
                );
232
            }
233
        } else {
234
            switch ($resampleDimension->getFocus()) {
235
                default:
236
                case 'CENTER':
237
                    $resampleAxis = new Dimension\Axis(
238
                        ($sourceDimension->getWidth() / 2) - ($resizeWidth / 2),
239
                        ($sourceDimension->getHeight() / 2) - ($resizeHeight / 2)
240
                    );
241
                    break;
242
                case 'NORTH':
243
                    $resampleAxis = new Dimension\Axis(
244
                        ($sourceDimension->getWidth() - $resizeWidth) / 2,
245
                        0
246
                    );
247
                    break;
248
                case 'NORTHWEST':
249
                    $resampleAxis = new Dimension\Axis(
250
                        0,
251
                        0
252
                    );
253
                    break;
254
                case 'NORTHEAST':
255
                    $resampleAxis = new Dimension\Axis(
256
                        $sourceDimension->getWidth() - $resizeWidth,
257
                        0
258
                    );
259
                    break;
260
                case 'SOUTH':
261
                    $resampleAxis = new Dimension\Axis(
262
                        ($sourceDimension->getWidth() - $resizeWidth) / 2,
263
                        $sourceDimension->getHeight() - $resizeHeight
264
                    );
265
                    break;
266
                case 'SOUTHWEST':
267
                    $resampleAxis = new Dimension\Axis(
268
                        0,
269
                        $sourceDimension->getHeight() - $resizeHeight
270
                    );
271
                    break;
272
                case 'SOUTHEAST':
273
                    $resampleAxis = new Dimension\Axis(
274
                        $sourceDimension->getWidth() - $resizeWidth,
275
                        $sourceDimension->getHeight() - $resizeHeight
276
                    );
277
                    break;
278
                case 'WEST':
279
                    $resampleAxis = new Dimension\Axis(
280
                        0,
281
                        ($sourceDimension->getHeight() - $resizeHeight) / 2
282
                    );
283
                    break;
284
                case 'EAST':
285
                    $resampleAxis = new Dimension\Axis(
286
                        $sourceDimension->getWidth() - $resizeWidth,
287
                        ($sourceDimension->getHeight() - $resizeHeight) / 2
288
                    );
289
                    break;
290
            }
291
292
            if ( ! $resampleImageResource->resizeImage(
293
                $sourceDimension->getWidth(),
294
                $sourceDimension->getHeight(),
295
                \Imagick::FILTER_CATROM, 0.9, true)
296
            ) {
297
                return false;
298
            }
299
        }
300
301
        if (isset($resampleAxis)) {
302
            return $this->crop($resampleDimension->withAxis($resampleAxis));
303
        }
304
305
        return false;
306
    }
307
308
    // ------------------------------------------------------------------------
309
310
    /**
311
     * ImagemagickDriver::crop
312
     *
313
     * Crop an image.
314
     *
315
     * @param \O2System\Image\Dimension $dimension
316
     *
317
     * @return bool
318
     */
319
    public function crop(Dimension $dimension)
320
    {
321
        $resampleImageResource =& $this->getResampleImageResource();
322
323
        try {
324
            return $resampleImageResource->cropImage(
325
                $dimension->getWidth(),
326
                $dimension->getHeight(),
327
                $dimension->getAxis()->getX(),
328
                $dimension->getAxis()->getY()
329
            );
330
        } catch (\ImagickException $e) {
331
            $this->errors[ $e->getCode() ] = $e->getMessage();
332
        }
333
334
        return false;
335
    }
336
337
    /**
338
     * ImagemagickDriver::watermark
339
     *
340
     * Watermark an image.
341
     *
342
     * @param \O2System\Image\Abstracts\AbstractWatermark $watermark
343
     *
344
     * @return bool
345
     */
346
    public function watermark(AbstractWatermark $watermark)
347
    {
348
        $resampleImageResource =& $this->getResampleImageResource();
349
350
        if ($watermark instanceof Text) {
351
352
            $draw = new \ImagickDraw();
353
            $draw->setFont($watermark->getFontPath());
354
            $draw->setFontSize($watermark->getFontSize());
355
            $draw->setFillColor($watermark->getFontColor());
0 ignored issues
show
Bug introduced by
$watermark->getFontColor() of type string is incompatible with the type ImagickPixel expected by parameter $fill_pixel of ImagickDraw::setFillColor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

355
            $draw->setFillColor(/** @scrutinizer ignore-type */ $watermark->getFontColor());
Loading history...
356
357
            if (false !== ($textAxis = $watermark->getAxis())) {
0 ignored issues
show
introduced by
The condition false !== $textAxis = $watermark->getAxis() is always true.
Loading history...
358
                $draw->annotation($textAxis->getX(), $textAxis->getY(), $watermark->getString());
359
            } else {
360
                switch ($watermark->getPosition()) {
361
                    default:
362
                    case 'MIDDLE_MIDDLE':
363
                    case 'MIDDLE':
364
                    case 'CENTER':
365
                        $draw->setGravity(\Imagick::GRAVITY_CENTER);
366
                        break;
367
368
                    case 'MIDDLE_LEFT':
369
                        $draw->setGravity(\Imagick::GRAVITY_WEST);
370
                        break;
371
372
                    case 'MIDDLE_RIGHT':
373
                        $draw->setGravity(\Imagick::GRAVITY_EAST);
374
                        break;
375
376
                    case 'MIDDLE_TOP':
377
                        $draw->setGravity(\Imagick::GRAVITY_NORTH);
378
                        break;
379
380
                    case 'MIDDLE_BOTTOM':
381
                        $draw->setGravity(\Imagick::GRAVITY_SOUTH);
382
                        break;
383
384
                    case 'TOP_LEFT':
385
                        $draw->setGravity(\Imagick::GRAVITY_NORTHWEST);
386
                        break;
387
388
                    case 'TOP_RIGHT':
389
                        $draw->setGravity(\Imagick::GRAVITY_NORTHEAST);
390
                        break;
391
392
                    case 'BOTTOM_LEFT':
393
                        $draw->setGravity(\Imagick::GRAVITY_SOUTHWEST);
394
                        break;
395
396
                    case 'BOTTOM_RIGHT':
397
                        $draw->setGravity(\Imagick::GRAVITY_SOUTHEAST);
398
                        break;
399
                }
400
            }
401
402
            return $resampleImageResource->annotateImage(
403
                $draw,
404
                $watermark->getPadding(),
405
                $watermark->getPadding(),
406
                $watermark->getAngle(),
407
                $watermark->getString()
408
            );
409
        } elseif ($watermark instanceof Overlay) {
410
            $watermarkImage = new self;
411
            $watermarkImage->setSourceImage($watermark->getImagePath());
412
            $watermarkImage->createFromSource();
413
414
            $watermarkImageFile = $watermarkImage->getSourceImageFile();
415
            $watermarkImageDimension = $watermarkImageFile->getDimension();
416
            $watermarkImageDimension->maintainAspectRatio = true;
417
418
            $resampleImageDimension = $this->resampleImageFile->getDimension();
419
420
            if (false === ($scale = $watermark->getImageScale())) {
0 ignored issues
show
introduced by
The condition false === $scale = $watermark->getImageScale() is always false.
Loading history...
421
                $scale = min(
422
                    round((($resampleImageDimension->getWidth() / 2) / $watermarkImageDimension->getWidth()) * 100),
423
                    round((($resampleImageDimension->getHeight() / 2) / $watermarkImageDimension->getHeight()) * 100)
424
                );
425
            }
426
427
            if ($scale > 0) {
428
                $watermarkImage->setResampleImage($watermarkImageFile->withDimension(
429
                    $watermarkImageDimension
430
                        ->withScale($scale)
431
                ));
432
            }
433
434
            $watermarkImageDimension = $watermarkImage->getResampleImageFile()->getDimension();
435
436
            if ($watermarkImage->scale()) {
437
                $watermarkImageResource = $watermarkImage->getResampleImageResource();
438
439
                if (false !== ($watermarkAxis = $watermark->getAxis())) {
0 ignored issues
show
introduced by
The condition false !== $watermarkAxis = $watermark->getAxis() is always true.
Loading history...
440
                    $watermarkImageAxisX = $watermarkAxis->getX();
441
                    $watermarkImageAxisY = $watermarkAxis->getY();
442
                } else {
443
                    switch ($watermark->getPosition()) {
444
                        default:
445
                        case 'MIDDLE_MIDDLE':
446
                        case 'MIDDLE':
447
                        case 'CENTER':
448
                            $watermarkImageAxisX = ($resampleImageDimension->getWidth() - $watermarkImageDimension->getWidth()) / 2;
449
                            $watermarkImageAxisY = ($resampleImageDimension->getHeight() - $watermarkImageDimension->getHeight()) / 2;
450
                            break;
451
452
                        case 'MIDDLE_LEFT':
453
                            $watermarkImageAxisX = $watermark->getPadding();
454
                            $watermarkImageAxisY = ($resampleImageDimension->getHeight() - $watermarkImageDimension->getHeight()) / 2;
455
                            break;
456
457
                        case 'MIDDLE_RIGHT':
458
                            $watermarkImageAxisX = $resampleImageDimension->getWidth() - ($watermarkImageDimension->getWidth() + $watermark->getPadding());
459
                            $watermarkImageAxisY = ($resampleImageDimension->getHeight() - $watermarkImageDimension->getHeight()) / 2;
460
                            break;
461
462
                        case 'MIDDLE_TOP':
463
                            $watermarkImageAxisX = ($resampleImageDimension->getWidth() - $watermarkImageDimension->getWidth()) / 2;
464
                            $watermarkImageAxisY = $watermarkImageDimension->getHeight() + $watermark->getPadding();
465
                            break;
466
467
                        case 'MIDDLE_BOTTOM':
468
                            $watermarkImageAxisX = ($resampleImageDimension->getWidth() - $watermarkImageDimension->getWidth()) / 2;
469
                            $watermarkImageAxisY = $resampleImageDimension->getHeight() - ($watermarkImageDimension->getHeight() + $watermark->getPadding());
470
                            break;
471
472
                        case 'TOP_LEFT':
473
                            $watermarkImageAxisX = $watermark->getPadding();
474
                            $watermarkImageAxisY = $watermarkImageDimension->getHeight() + $watermark->getPadding();
475
                            break;
476
477
                        case 'TOP_RIGHT':
478
                            $watermarkImageAxisX = $resampleImageDimension->getWidth() - ($watermarkImageDimension->getWidth() + $watermark->getPadding());
479
                            $watermarkImageAxisY = $watermarkImageDimension->getHeight() + $watermark->getPadding();
480
                            break;
481
482
                        case 'BOTTOM_LEFT':
483
                            $watermarkImageAxisX = $watermark->getPadding();
484
                            $watermarkImageAxisY = $resampleImageDimension->getHeight() - $watermarkImageDimension->getHeight() + $watermark->getPadding();
485
                            break;
486
487
                        case 'BOTTOM_RIGHT':
488
                            $watermarkImageAxisX = $resampleImageDimension->getWidth() - ($watermarkImageDimension->getWidth() + $watermark->getPadding());
489
                            $watermarkImageAxisY = $resampleImageDimension->getHeight() - ($watermarkImageDimension->getHeight() + $watermark->getPadding());
490
                            break;
491
                    }
492
                }
493
494
                try {
495
                    $resampleImageResource->compositeImage($watermarkImageResource, \Imagick::COMPOSITE_OVER,
496
                        $watermarkImageAxisX,
497
                        $watermarkImageAxisY);
498
499
                    return true;
500
                } catch (\ImagickException $e) {
501
                    $this->errors[ $e->getCode() ] = $e->getMessage();
502
                }
503
            }
504
        }
505
506
        return false;
507
    }
508
509
    // ------------------------------------------------------------------------
510
511
    /**
512
     * ImagemagickDriver::createFromSource
513
     *
514
     * Create an image resource from source file.
515
     *
516
     * @return static
517
     */
518
    public function createFromSource()
519
    {
520
        $this->sourceImageResource = new \Imagick($this->sourceImageFile->getRealPath());
521
    }
522
523
    // ------------------------------------------------------------------------
524
525
    /**
526
     * ImagemagickDriver::scale
527
     *
528
     * Scale an image with a given scale.
529
     *
530
     * @return bool
531
     */
532
    public function scale()
533
    {
534
        $resampleDimension = $this->resampleImageFile->getDimension();
535
536
        $resampleImageResource =& $this->getResampleImageResource();
537
538
        try {
539
            return $resampleImageResource->scaleImage($resampleDimension->getWidth(), $resampleDimension->getHeight(),
540
                true);
541
        } catch (\ImagickException $e) {
542
            $this->errors[ $e->getCode() ] = $e->getMessage();
543
        }
544
545
        return false;
546
    }
547
548
    // ------------------------------------------------------------------------
549
550
    /**
551
     * ImagemagickDriver::display
552
     *
553
     * Display an image.
554
     *
555
     * @return void
556
     */
557
    public function display($quality = 100, $mime = null)
558
    {
559
        $filename = pathinfo($this->sourceImageFile->getBasename(), PATHINFO_FILENAME);
560
        $extension = pathinfo($this->sourceImageFile->getBasename(), PATHINFO_EXTENSION);
561
562
        if (empty($mime)) {
563
            $mime = $this->sourceImageFile->getMime();
564
            $mime = is_array($mime) ? $mime[ 0 ] : $mime;
565
566
            $extension = $this->getMimeExtension($mime);
567
        }
568
569
        header('Content-Disposition: filename=' . $filename . '.' . $extension);
0 ignored issues
show
Bug introduced by
Are you sure $extension of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

569
        header('Content-Disposition: filename=' . $filename . '.' . /** @scrutinizer ignore-type */ $extension);
Loading history...
570
        header('Content-Transfer-Encoding: binary');
571
        header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
572
        header('Content-Type: ' . $mime);
573
574
        $blob = $this->blob($quality);
575
576
        header('ETag: ' . md5($blob));
577
578
        echo $blob;
579
580
        exit(0);
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
581
    }
582
583
    // ------------------------------------------------------------------------
584
585
    /**
586
     * ImagemagickDriver::blob
587
     *
588
     * Returns image string blob.
589
     *
590
     * @return string
591
     */
592
    public function blob($quality = 100, $mime = null)
593
    {
594
        $imageBlob = '';
595
596
        $filename = pathinfo($this->sourceImageFile->getBasename(), PATHINFO_FILENAME);
597
        $extension = pathinfo($this->sourceImageFile->getBasename(), PATHINFO_EXTENSION);
598
599
        if (empty($mime)) {
600
            $mime = $this->sourceImageFile->getMime();
601
            $mime = is_array($mime) ? $mime[ 0 ] : $mime;
602
603
            $extension = $this->getMimeExtension($mime);
604
        }
605
606
        header('Content-Disposition: filename=' . $filename . '.' . $extension);
0 ignored issues
show
Bug introduced by
Are you sure $extension of type false|mixed|string can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

606
        header('Content-Disposition: filename=' . $filename . '.' . /** @scrutinizer ignore-type */ $extension);
Loading history...
607
608
        if ($this->save($tempImageFilePath = rtrim(sys_get_temp_dir(),
609
                DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . $filename . '.' . $extension,
610
            $quality)
611
        ) {
612
            $imageBlob = readfile($tempImageFilePath);
613
            unlink($tempImageFilePath);
614
        }
615
616
        return $imageBlob;
617
    }
618
619
    // ------------------------------------------------------------------------
620
621
    /**
622
     * ImagemagickDriver::save
623
     *
624
     * Save an image.
625
     *
626
     * @param string $imageTargetFilePath
627
     * @param int    $quality
628
     *
629
     * @return bool
630
     */
631
    public function save($imageTargetFilePath, $quality = 100)
632
    {
633
        $resampleImageResource =& $this->getResampleImageResource();
634
635
        $extension = pathinfo($imageTargetFilePath, PATHINFO_EXTENSION);
636
637
        switch ($extension) {
638
            case 'jpg':
639
            case 'jpeg':
640
                $resampleImageResource->setImageFormat('jpg');
641
                $resampleImageResource->setCompression(\Imagick::COMPRESSION_LOSSLESSJPEG);
642
                break;
643
644
            case 'gif':
645
                $resampleImageResource->setImageFormat('gif');
646
                $resampleImageResource->setCompression(\Imagick::COMPRESSION_UNDEFINED);
647
                break;
648
649
            case 'png':
650
                $resampleImageResource->setImageFormat('png');
651
                $resampleImageResource->setCompression(\Imagick::COMPRESSION_UNDEFINED);
652
                $resampleImageResource->setImageAlphaChannel(\Imagick::ALPHACHANNEL_ACTIVATE);
653
                $resampleImageResource->setBackgroundColor(new \ImagickPixel('transparent'));
654
                break;
655
656
            case 'webp':
657
                $resampleImageResource->setImageFormat('webp');
658
                $resampleImageResource->setCompression(\Imagick::COMPRESSION_UNDEFINED);
659
                $resampleImageResource->setImageAlphaChannel(\Imagick::ALPHACHANNEL_ACTIVATE);
660
                $resampleImageResource->setBackgroundColor(new \ImagickPixel('transparent'));
661
                break;
662
        }
663
664
        $resampleImageResource->setCompressionQuality($quality);
665
        $resampleImageResource->stripImage();
666
667
        return (bool)$resampleImageResource->writeImage($imageTargetFilePath);
668
    }
669
}