Passed
Push — master ( 4fa1fd...50ce38 )
by compolom
02:04
created

GD::resize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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