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

GD::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
eloc 2
nop 1
1
<?php declare(strict_types=1);
2
3
namespace Compolomus\Compomage;
4
5
use Compolomus\Compomage\Interfaces\ImageInterface;
6
7
class GD extends AbstractImage implements ImageInterface
8
{
9
    /**
10
     * @var resource
11
     */
12
    private $image;
13
14
    /**
15
     * GD constructor.
16
     * @param string $image
17
     * @throws \Exception
18
     */
19
    public function __construct(string $image)
20
    {
21
        $this->init($image);
22
    }
23
24
    public function flip(): ImageInterface
25
    {
26
        imageflip($this->getImage(), IMG_FLIP_VERTICAL);
27
28
        return $this;
29
    }
30
31
    /**
32
     * @return resource
33
     */
34
    public function getImage()
35
    {
36
        return $this->image;
37
    }
38
39
    public function setImage($image): void
40
    {
41
        $this->image = $image;
42
    }
43
44
    public function flop(): ImageInterface
45
    {
46
        imageflip($this->getImage(), IMG_FLIP_HORIZONTAL);
47
48
        return $this;
49
    }
50
51
    public function grayscale(): ImageInterface
52
    {
53
        imagefilter($this->getImage(), IMG_FILTER_GRAYSCALE);
54
55
        return $this;
56
    }
57
58
    /**
59
     * @param string $text
60
     * @param string $font
61
     * @param string $position
62
     * @return $this
63
     * @throws \Exception
64
     */
65
    public function copyright(string $text, string $font, string $position = 'SouthWest'): ImageInterface
66
    {
67
        if (!array_key_exists(strtoupper($position), self::POSITIONS)) {
68
            throw new \InvalidArgumentException('Wrong position');
69
        }
70
71
        imagecopymerge(
72
            $this->getImage(),
73
            $image = $this->prepareImage($text, $font),
74
            (int)((($this->getWidth() - imagesx($image)) / 2) * self::POSITIONS[strtoupper($position)]['x']) + self::POSITIONS[strtoupper($position)]['padX'],
75
            (int)((($this->getHeight() - imagesy($image)) / 2) * self::POSITIONS[strtoupper($position)]['y']) + self::POSITIONS[strtoupper($position)]['padY'],
76
            0,
77
            0,
78
            $this->getWidth(),
79
            $this->getHeight(),
80
            80
81
        );
82
83
        return $this;
84
    }
85
86
    /**
87
     * @param string $text
88
     * @param string $font
89
     * @return resource
90
     * @throws \Exception
91
     */
92
    private function prepareImage(string $text, string $font)
93
    {
94
        if (!$coordinates = imagettfbbox($fontSize = 15, 0, $font, $text)) {
95
            throw new \InvalidArgumentException('Does not support font');
96
        }
97
98
        $minX = min([$coordinates[0], $coordinates[2], $coordinates[4], $coordinates[6]]);
99
        $maxX = max([$coordinates[0], $coordinates[2], $coordinates[4], $coordinates[6]]);
100
        $minY = min([$coordinates[1], $coordinates[3], $coordinates[5], $coordinates[7]]);
101
        $maxY = max([$coordinates[1], $coordinates[3], $coordinates[5], $coordinates[7]]);
102
        $textX = (int)abs($minX) + 1;
103
        $textY = (int)abs($minY) + 1;
104
        $image = $this->newImage($maxX - $minX + 2, $maxY - $minY + 2);
105
        imagecolortransparent($image, $white = imagecolorallocate($image, 0, 0, 0));
106
        imagefilledrectangle($image, 0, 0, $this->getWidth(), 20, $white);
107
        imagettftext($image, $fontSize, 0, $textX, $textY, $white, $font, $text);
108
        imagettftext($image, $fontSize, 0, $textX + 1, $textY + 1, $blue = imagecolorallocate($image, 0, 128, 128),
109
            $font, $text);
110
        imagettftext($image, $fontSize, 0, $textX + 1, $textY + 1, $red = imagecolorallocate($image, 255, 0, 0), $font,
111
            $text);
112
        imagettftext($image, $fontSize, 0, $textX + 2, $textY + 2, $black = imagecolorallocate($image, 255, 255, 255),
113
            $font, $text);
114
        imagettftext($image, $fontSize, 0, $textX + 2, $textY + 2, $gray = imagecolorallocate($image, 128, 128, 128),
115
            $font, $text);
116
117
        return $image;
118
    }
119
120
    private function newImage(int $width, int $height)
121
    {
122
        $newimg = imagecreatetruecolor($width, $height);
123
        $transparent = imagecolorallocatealpha($newimg, 255, 255, 255, 127);
124
        imagefill($newimg, 0, 0, $transparent);
125
        imagealphablending($newimg, true);
126
        imagesavealpha($newimg, true);
127
128
        return $newimg;
129
    }
130
131
    public function resize(int $width, int $height): ImageInterface
132
    {
133
        $newimage = $this->newImage($width, $height);
134
        imagecopyresampled($newimage, $this->getImage(), 0, 0, 0, 0, $width, $height, $this->getWidth(),
135
            $this->getHeight());
136
        $this->setImage($newimage);
137
        $this->setSizes();
138
139
        return $this;
140
    }
141
142
    protected function setSizes(): void
143
    {
144
        $this->setWidth(imagesx($this->getImage()));
145
        $this->setHeight(imagesy($this->getImage()));
146
    }
147
148
    public function crop(int $width, int $height, int $x, int $y): ImageInterface
149
    {
150
        $width -= $x;
151
        $height -= $y;
152
        $newimage = $this->newImage($width, $height);
153
        imagecopyresampled($newimage, $this->getImage(), 0, 0, $x, $y, $width, $height, $width, $height);
154
        $this->setImage($newimage);
155
        $this->setSizes();
156
157
        return $this;
158
    }
159
160
    public function rotate(int $angle = 90): ImageInterface
161
    {
162
        $transparent = imagecolorallocatealpha($this->image, 0, 0, 0, 127);
163
        $rotate = imagerotate($this->getImage(), $angle, $transparent);
164
        imagealphablending($rotate, true);
165
        imagesavealpha($rotate, true);
166
        $this->setImage($rotate);
167
        $this->setSizes();
168
169
        return $this;
170
    }
171
172
    public function __toString(): string
173
    {
174
        ob_start();
175
        imagepng($this->getImage(), null, 9, PNG_ALL_FILTERS);
176
        $temp = ob_get_contents();
177
        ob_clean();
178
179
        return trim($temp);
180
    }
181
182
    public function save(string $filename): bool
183
    {
184
        return true;
185
    }
186
187
    protected function prepareThumbnail(
188
        int $width,
189
        int $height,
190
        int $newWidth = 0,
191
        int $newHeight = 0
192
    ): ImageInterface {
193
        imagecopyresampled(
194
            $newimage = $this->newImage($width, $height),
195
            $this->getImage(),
196
            0 - (int)(($newWidth - $width) / 2),
197
            0 - (int)(($newHeight - $height) / 2),
198
            0,
199
            0,
200
            $newWidth,
201
            $newHeight,
202
            $this->getWidth(),
203
            $this->getHeight()
204
        );
205
        $this->setImage($newimage);
206
        $this->setSizes();
207
208
        return $this;
209
    }
210
211
    /**
212
     * @param string $source
213
     * @return ImageInterface
214
     * @throws \Exception
215
     */
216
    protected function tmp(string $source): ImageInterface
217
    {
218
        $image = imagecreatefromstring($source);
219
        if (!\is_resource($image)) {
220
            throw new \InvalidArgumentException('Image create failed');
221
        }
222
        $this->setImage($image);
223
        $this->setSizes();
224
        // save transparent
225
        imagesavealpha($this->getImage(), true);
226
        imagealphablending($this->getImage(), false);
227
228
        return $this;
229
    }
230
231
    /**
232
     * @param Image $watermark
233
     * @param int $x
234
     * @param int $y
235
     * @return ImageInterface
236
     */
237
    protected function prepareWatermark(Image $watermark, int $x, int $y): ImageInterface
238
    {
239
        imagealphablending($this->getImage(), true);
240
        imagesavealpha($this->getImage(), true);
241
        imagecopyresampled(
242
            $this->getImage(),
243
            $watermark->getImage(),
244
            $x,
245
            $y,
246
            0,
247
            0,
248
            $width = (int)$watermark->getWidth(),
249
            $height = (int)$watermark->getHeight(),
250
            $width,
251
            $height
252
        );
253
254
        return $this;
255
    }
256
}
257