Passed
Branch master (a17811)
by compolom
03:05 queued 01:14
created

Imagick::prepareWatermark()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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