Passed
Pull Request — master (#1)
by compolom
02:43
created

Imagick2::prepareThumbnail()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php declare(strict_types=1);
2
3
namespace Compolomus\Compomage;
4
5
use Compolomus\Compomage\Interfaces\ImageInterface;
6
use Exception;
7
use Imagick;
8
use ImagickDraw;
9
use ImagickException;
10
use ImagickPixel;
11
use InvalidArgumentException;
12
13
class Imagick2 extends AbstractImage
14
{
15
    /**
16
     * Imagick constructor.
17
     * @param string $image
18
     * @throws Exception
19
     */
20 9
    public function __construct(string $image)
21
    {
22 9
        $this->init($image);
23 9
    }
24
25
    /**
26
     * @param int $width
27
     * @param int $height
28
     * @return ImageInterface
29
     * @throws ImagickException
30
     */
31 1
    public function resize(int $width, int $height): ImageInterface
32
    {
33 1
        $this->getImage()->scaleImage($width, $height, false);
34 1
        $this->setSizes();
35
36 1
        return $this;
37
    }
38
39 9
    protected function setSizes(): void
40
    {
41 9
        $args = $this->getImage()->getImageGeometry();
42 9
        $this->setWidth($args['width']);
43 9
        $this->setHeight($args['height']);
44 9
        $this->setOrientation();
45 9
    }
46
47
    /**
48
     * @param int $angle
49
     * @return ImageInterface
50
     */
51 1
    public function rotate(int $angle = 90): ImageInterface
52
    {
53 1
        $this->getImage()->rotateImage(new ImagickPixel('transparent'), $angle);
54 1
        $this->setSizes();
55
56 1
        return $this;
57
    }
58
59
    /**
60
     * @return ImageInterface
61
     */
62
    public function flip(): ImageInterface
63
    {
64
        $this->getImage()->flipImage();
65
66
        return $this;
67
    }
68
69
    /**
70
     * @return ImageInterface
71
     */
72
    public function flop(): ImageInterface
73
    {
74
        $this->getImage()->flopImage();
75
76
        return $this;
77
    }
78
79
    public function grayscale(): ImageInterface
80
    {
81
        $this->getImage()->transformimagecolorspace(Imagick::COLORSPACE_GRAY);
82
        $this->getImage()->separateImageChannel(1);
83
84
        // modulateImage(100, 0, 100);
85
86
        return $this;
87
    }
88
89
    /**
90
     * @param string $text
91
     * @param string $position
92
     * @param string $font
93
     * @return ImageInterface
94
     * @throws InvalidArgumentException
95
     * @throws ImagickException
96
     */
97 1
    public function copyright(string $text, string $font = 'Courier', string $position = 'SouthWest'): ImageInterface
98
    {
99
        $positions = [
100 1
            'NORTHWEST' => Imagick::GRAVITY_NORTHWEST,
101
            'NORTH' => Imagick::GRAVITY_NORTH,
102
            'NORTHEAST' => Imagick::GRAVITY_NORTHEAST,
103
            'WEST' => Imagick::GRAVITY_WEST,
104
            'CENTER' => Imagick::GRAVITY_CENTER,
105
            'SOUTHWEST' => Imagick::GRAVITY_SOUTHWEST,
106
            'SOUTH' => Imagick::GRAVITY_SOUTH,
107
            'SOUTHEAST' => Imagick::GRAVITY_SOUTHEAST,
108
            'EAST' => Imagick::GRAVITY_EAST
109
        ];
110 1
        if (!array_key_exists(strtoupper($position), $positions) || !in_array($font, $this->getFontsList(), true)) {
111 1
            throw new InvalidArgumentException('Does not support font or wrong position');
112
        }
113
        $this->getImage()->compositeImage($this->prepareImage($text, $positions[strtoupper($position)], $font),
114
            Imagick::COMPOSITE_DISSOLVE, 0, 0);
115
116
        return $this;
117
    }
118
119 1
    public function getFontsList(): array
120
    {
121 1
        return $this->getImage()->queryFonts();
122
    }
123
124
    /**
125
     * @param string $text
126
     * @param int $position
127
     * @param string $font
128
     * @return Imagick
129
     * @throws ImagickException
130
     */
131
    private function prepareImage(string $text, int $position, string $font): Imagick
132
    {
133
        $image = new Imagick();
134
        $mask = new Imagick();
135
        $draw = new ImagickDraw();
136
        $image->newImage($this->getWidth(), $this->getHeight(), new ImagickPixel('grey30'));
137
        $mask->newImage($this->getWidth(), $this->getHeight(), new ImagickPixel('black'));
138
        $draw->setFont($font);
139
        $draw->setFontSize(20);
140
        $draw->setFillColor(new ImagickPixel('grey70'));
141
        $draw->setGravity($position);
142
        $image->annotateImage($draw, 10, 12, 0, $text);
143
        $draw->setFillColor(new ImagickPixel('white'));
144
        $mask->annotateImage($draw, 11, 13, 0, $text);
145
        $mask->annotateImage($draw, 10, 12, 0, $text);
146
        $draw->setFillColor(new ImagickPixel('black'));
147
        $mask->annotateImage($draw, 9, 11, 0, $text);
148
        $mask->setImageMatte(false);
149
        $image->compositeImage($mask, Imagick::COMPOSITE_COPYOPACITY, 0, 0);
150
151
        return $image;
152
    }
153
154
    /**
155
     * @param int $width
156
     * @param int $height
157
     * @param int $startX
158
     * @param int $startY
159
     * @return ImageInterface
160
     */
161
    public function crop(int $width, int $height, int $startX, int $startY): ImageInterface
162
    {
163
        $this->getImage()->cropImage($width, $height, $startX, $startY);
164
        $this->setSizes();
165
166
        return $this;
167
    }
168
169 1
    public function save(string $filename, $quality = 100): bool
170
    {
171 1
        $this->getImage()->setImageCompressionQuality($quality);
172 1
        $this->getImage()->writeImage($filename . '.png');
173
174 1
        return true;
175
    }
176
177 1
    public function __toString(): string
178
    {
179 1
        return trim($this->getImage()->getImageBlob());
180
    }
181
182
    /**
183
     * @param int $width
184
     * @param int $height
185
     * @return ImageInterface
186
     * @throws ImagickException
187
     */
188 1
    protected function prepareThumbnail(int $width, int $height): ImageInterface
189
    {
190 1
        $this->getImage()->cropThumbnailImage($width, $height);
191
192 1
        return $this;
193
    }
194
195
    /**
196
     * @param string $source
197
     * @return ImageInterface
198
     * @throws ImagickException
199
     */
200 9
    protected function tmp(string $source): ImageInterface
201
    {
202 9
        $image = new Imagick;
203 9
        if ($image->readImageBlob($source)) {
204 9
            if ($image->getImageAlphaChannel() !== Imagick::ALPHACHANNEL_ACTIVATE) {
205 8
                $image->setImageAlphaChannel(Imagick::ALPHACHANNEL_SET);
206
            }
207
        }
208 9
        $background = $this->newImage($image->getImageWidth(), $image->getImageHeight());
209 9
        $image->compositeImage($background, Imagick::COMPOSITE_OVER, 0, 0); //Imagick::COMPOSITE_DISSOLVE
210 9
        $this->setImage($image);
211 9
        $this->getImage()->setFormat('png'); // save transparent
212 9
        $this->setSizes();
213
214 9
        return $this;
215
    }
216
217
    /**
218
     * @param int $width
219
     * @param int $height
220
     * @return Imagick
221
     * @throws ImagickException
222
     */
223 9
    protected function newImage(int $width, int $height): Imagick
224
    {
225 9
        $background = new Imagick;
226 9
        $background->newImage($width, $height, new ImagickPixel('transparent'));
227 9
        $background->setImageBackgroundColor(new ImagickPixel('transparent'));
228
229 9
        return $background;
230
    }
231
232
    /**
233
     * @param Image $watermark
234
     * @param int $x
235
     * @param int $y
236
     * @return ImageInterface
237
     * @throws Exception
238
     */
239
    protected function prepareWatermark($watermark, int $x, int $y): ImageInterface
240
    {
241
        $watermark = $watermark->getImage();
242
        $watermark->evaluateImage(Imagick::EVALUATE_MULTIPLY, 1, Imagick::CHANNEL_ALPHA);
243
        $this->getImage()->compositeImage($watermark, Imagick::COMPOSITE_DISSOLVE, $x, $y);
244
245
        return $this;
246
    }
247
248
    public function resizeByTransparentBackground(int $width, int $height): ImageInterface
249
    {
250
        $background = $this->newImage($width, $height);
251
        $background->setImageFormat('png');
252
253
        return $this->setBackground($width, $height, new Image(base64_encode((string) $background), Image::IMAGICK));
254
    }
255
256 View Code Duplication
    public function resizeByBlurBackground(int $width, int $height): ImageInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
257
    {
258
        $background = new Image(base64_encode((string) $this));
259
        $background->resize($width, $height)->blur();
260
261
        return $this->setBackground($width, $height, $background);
262
    }
263
264
    /**
265
     * @param int $level
266
     * @return ImageInterface
267
     */
268 View Code Duplication
    public function brightness(int $level): ImageInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
269
    {
270
        if (!$this->compareRangeValue($level, 200))
271
        {
272
            throw new InvalidArgumentException('Wrong brightness level, range 0 - 200, ' . $level . ' given');
273
        }
274
        $this->getImage()->modulateImage(abs($level), 100, 100);
275
276
        return $this;
277
    }
278
279
    /**
280
     * @param int $level
281
     * @return ImageInterface
282
     */
283 View Code Duplication
    public function contrast(int $level): ImageInterface
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
284
    {
285
        if (!$this->compareRangeValue($level, 100))
286
        {
287
            throw new InvalidArgumentException('Wrong contrast level, range 0 - 100, ' . $level . ' given');
288
        }
289
        $this->getImage()->brightnessContrastImage(0, abs($level));
0 ignored issues
show
Bug introduced by
The method brightnessContrastImage() does not exist on Imagick. Did you maybe mean contrastimage()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
290
291
        return $this;
292
    }
293
294
    /**
295
     * @return ImageInterface
296
     */
297
    public function negate(): ImageInterface
298
    {
299
        $this->getImage()->negateImage(false);
300
301
        return $this;
302
    }
303
304
    /**
305
     * @return ImageInterface
306
     */
307
    public function blur(): ImageInterface
308
    {
309
        $this->getImage()->blurImage(7, 5);
310
311
        return $this;
312
    }
313
}
314