Completed
Push — master ( 80eb51...d7d63e )
by Oscar
7s
created

Gd::getImage()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
3
namespace Imagecow\Libs;
4
5
use Imagecow\ImageException;
6
use Imagecow\Utils;
7
8
/**
9
 * GD library.
10
 */
11
class Gd extends AbstractLib implements LibInterface
12
{
13
    public static $fallbackCropMethods = [
14
        'Entropy' => ['center', 'middle'],
15
        'Balanced' => ['center', 'middle'],
16
    ];
17
18
    protected $image;
19
    protected $type;
20
21
    /**
22
     * {@inheritdoc}
23
     */
24
    public static function checkCompatibility()
25
    {
26
        return extension_loaded('gd');
27
    }
28
29
    /**
30
     * {@inheritdoc}
31
     */
32
    public static function createFromFile($filename)
33
    {
34
        $data = getImageSize($filename);
35
36
        if (empty($data) || !is_array($data)) {
37
            throw new ImageException("The image file '{$filename}' cannot be loaded");
38
        }
39
40
        $function = 'imagecreatefrom'.image_type_to_extension($data[2], false);
41
42
        if (function_exists($function)) {
43
            return new static($function($filename), $data[2]);
44
        }
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public static function createFromString($string)
51
    {
52
        if (($image = imagecreatefromstring($string))) {
53
            return new static($image);
54
        }
55
56
        throw new ImageException('Error creating the image from string');
57
    }
58
59
    /**
60
     * Constructor of the class.
61
     *
62
     * @param resource $image The Gd resource.
63
     */
64
    public function __construct($image, $type = null)
65
    {
66
        $this->image = $image;
67
        $this->type = isset($type) ? $type : IMAGETYPE_PNG;
68
69
        imagealphablending($this->image, true);
70
        imagesavealpha($this->image, true);
71
        imagesetinterpolation($this->image, IMG_BICUBIC);
72
    }
73
74
    /**
75
     * Destroy the image.
76
     */
77
    public function __destruct()
78
    {
79
        imagedestroy($this->image);
80
    }
81
82
    /**
83
     * {@inheritdoc}
84
     */
85
    public function flip()
86
    {
87
        imageflip($this->image, IMG_FLIP_VERTICAL);
88
    }
89
90
    /**
91
     * {@inheritdoc}
92
     */
93
    public function flop()
94
    {
95
        imageflip($this->image, IMG_FLIP_HORIZONTAL);
96
    }
97
98
    /**
99
     * {@inheritdoc}
100
     */
101
    public function save($filename)
102
    {
103
        $extension = image_type_to_extension($this->type, false);
104
        $function = 'image'.$extension;
105
106
        if (!function_exists($function) || ($function($this->image, $filename) === false)) {
107
            throw new ImageException("The image format '{$extension}' cannot be saved to '{$filename}'");
108
        }
109
    }
110
111
    /**
112
     * Gets the original image object.
113
     *
114
     * @return resource
115
     */
116
    public function getImage()
117
    {
118
        return $this->image;
119
    }
120
121
    /**
122
     * {@inheritdoc}
123
     */
124
    public function getString()
125
    {
126
        $extension = image_type_to_extension($this->type, false);
127
        $function = 'image'.$extension;
128
129
        if (!function_exists($function)) {
130
            throw new ImageException("The image format '{$extension}' cannot be exported");
131
        }
132
133
        ob_start();
134
135
        if ($extension === 'jpeg') {
136
            $function($this->image, null, $this->quality);
137
        } else {
138
            $function($this->image);
139
        }
140
141
        return ob_get_clean();
142
    }
143
144
    /**
145
     * {@inheritdoc}
146
     */
147
    public function getMimeType()
148
    {
149
        return image_type_to_mime_type($this->type);
150
    }
151
152
    /**
153
     * {@inheritdoc}
154
     */
155
    public function getWidth()
156
    {
157
        return imagesx($this->image);
158
    }
159
160
    /**
161
     * {@inheritdoc}
162
     */
163
    public function getHeight()
164
    {
165
        return imagesy($this->image);
166
    }
167
168
    /**
169
     * {@inheritdoc}
170
     */
171
    public function format($format)
172
    {
173
        switch (strtolower($format)) {
174
            case 'jpg':
175
            case 'jpeg':
176
                $width = $this->getWidth();
177
                $height = $this->getHeight();
178
179
                if (($image = imagecreatetruecolor($width, $height)) === false) {
180
                    throw new ImageException('Error creating a image');
181
                }
182
183
                if (imagesavealpha($image, true) === false) {
184
                    throw new ImageException('Error saving the alpha chanel of the image');
185
                }
186
187
                if (isset($this->background[3])) {
188
                    $background = imagecolorallocatealpha($image, $this->background[0], $this->background[1], $this->background[2], $this->background[3]);
189
                } else {
190
                    $background = imagecolorallocate($image, $this->background[0], $this->background[1], $this->background[2]);
191
                }
192
193
                if (imagefill($image, 0, 0, $background) === false) {
194
                    throw new ImageException('Error filling the image');
195
                }
196
197
                imagecopy($image, $this->image, 0, 0, 0, 0, $width, $height);
198
199
                $this->image = $image;
200
                $this->type = IMAGETYPE_JPEG;
201
                break;
202
203
            case 'gif':
204
                $this->type = IMAGETYPE_GIF;
205
                break;
206
207
            case 'png':
208
                $this->type = IMAGETYPE_PNG;
209
                break;
210
211
            default:
212
                throw new ImageException("The image format '{$format}' is not valid");
213
        }
214
    }
215
216
    /**
217
     * {@inheritdoc}
218
     */
219
    public function resize($width, $height)
220
    {
221
        if (($image = imagescale($this->image, $width, $height, IMG_BICUBIC)) === false) {
222
            throw new ImageException('Error resizing the image');
223
        }
224
225
        $this->image = $image;
226
    }
227
228
    /**
229
     * {@inheritdoc}
230
     */
231
    public function getCropOffsets($width, $height, $method)
232
    {
233
        if (isset(static::$fallbackCropMethods[$method])) {
234
            return static::$fallbackCropMethods[$method];
235
        }
236
237
        throw new ImageException("The crop method '$method' is not available for Gd");
238
    }
239
240
    /**
241
     * {@inheritdoc}
242
     */
243
    public function crop($width, $height, $x, $y)
244
    {
245
        $crop = [
246
            'width' => $width,
247
            'height' => $height,
248
            'x' => $x,
249
            'y' => $y,
250
        ];
251
252
        if (($image = imagecrop($this->image, $crop)) === false) {
253
            throw new ImageException('Error cropping the image');
254
        }
255
256
        $this->image = $image;
257
    }
258
259
    /**
260
     * {@inheritdoc}
261
     */
262
    public function rotate($angle)
263
    {
264
        $background = imagecolorallocatealpha($this->image, 0, 0, 0, 127);
265
266
        if ($background === false || ($image = imagerotate($this->image, $angle, $background)) === false) {
267
            throw new ImageException('Error rotating the image');
268
        }
269
270
        $this->image = $image;
271
    }
272
273
    /**
274
     * @param resource $watermark Watermark image resource
275
     * @param array    $x         Position x
276
     * @param array    $y         Position y
277
     */
278
    public function watermark($watermark, $x, $y)
279
    {
280
        imagecopy($this->image, $watermark, $x, $y, 0, 0, imagesx($watermark), imagesy($watermark));
281
    }
282
283
    /**
284
     * {@inheritdoc}
285
     */
286
    public function opacity($opacity)
287
    {
288
        if ((int)$opacity === 100) {
289
            return;
290
        }
291
292
        $opacity = $opacity / 100;
293
294
        $width = $this->getWidth();
295
        $height = $this->getHeight();
296
297
        imagealphablending($this->image, false);
298
299
        for ($x = 0; $x < $width; ++$x) {
300
            for ($y = 0; $y < $height; ++$y) {
301
                $color = imagecolorat($this->image, $x, $y);
302
                $alpha = 127 - (($color >> 24) & 0xFF);
303
304
                if ($alpha <= 0) {
305
                    continue;
306
                }
307
308
                $color = ($color & 0xFFFFFF) | ((int)round(127 - $alpha * $opacity) << 24);
309
310
                imagesetpixel($this->image, $x, $y, $color);
311
            }
312
        }
313
    }
314
}
315