|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Imagecow\Libs; |
|
4
|
|
|
|
|
5
|
|
|
use Imagecow\ImageException; |
|
6
|
|
|
|
|
7
|
|
|
/** |
|
8
|
|
|
* GD library. |
|
9
|
|
|
*/ |
|
10
|
|
|
class Gd extends AbstractLib implements LibInterface |
|
11
|
|
|
{ |
|
12
|
|
|
public static $fallbackCropMethods = [ |
|
13
|
|
|
'Entropy' => ['center', 'middle'], |
|
14
|
|
|
'Balanced' => ['center', 'middle'], |
|
15
|
|
|
]; |
|
16
|
|
|
|
|
17
|
|
|
protected $image; |
|
18
|
|
|
protected $type; |
|
19
|
|
|
|
|
20
|
|
|
/** |
|
21
|
|
|
* {@inheritdoc} |
|
22
|
|
|
*/ |
|
23
|
|
|
public static function checkCompatibility() |
|
24
|
|
|
{ |
|
25
|
|
|
return extension_loaded('gd'); |
|
26
|
|
|
} |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* {@inheritdoc} |
|
30
|
|
|
*/ |
|
31
|
|
|
public static function createFromFile($filename) |
|
32
|
|
|
{ |
|
33
|
|
|
$data = @getImageSize($filename); |
|
34
|
|
|
|
|
35
|
|
|
if ($data && is_array($data)) { |
|
36
|
|
|
$function = 'imagecreatefrom'.image_type_to_extension($data[2], false); |
|
37
|
|
|
|
|
38
|
|
|
if (function_exists($function)) { |
|
39
|
|
|
return new static($function($filename), $data[2]); |
|
40
|
|
|
} |
|
41
|
|
|
} |
|
42
|
|
|
|
|
43
|
|
|
throw new ImageException("The image file '{$filename}' cannot be loaded"); |
|
44
|
|
|
} |
|
45
|
|
|
|
|
46
|
|
|
/** |
|
47
|
|
|
* {@inheritdoc} |
|
48
|
|
|
*/ |
|
49
|
|
|
public static function createFromString($string) |
|
50
|
|
|
{ |
|
51
|
|
|
if (($image = @imagecreatefromstring($string))) { |
|
52
|
|
|
return new static($image); |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
throw new ImageException('Error creating the image from string'); |
|
56
|
|
|
} |
|
57
|
|
|
|
|
58
|
|
|
/** |
|
59
|
|
|
* Constructor of the class. |
|
60
|
|
|
* |
|
61
|
|
|
* @param resource $image The Gd resource. |
|
62
|
|
|
*/ |
|
63
|
|
|
public function __construct($image, $type = null) |
|
64
|
|
|
{ |
|
65
|
|
|
$this->image = $image; |
|
66
|
|
|
$this->type = isset($type) ? $type : IMAGETYPE_PNG; |
|
67
|
|
|
|
|
68
|
|
|
imagealphablending($this->image, true); |
|
69
|
|
|
imagesavealpha($this->image, true); |
|
70
|
|
|
imagesetinterpolation($this->image, IMG_BICUBIC); |
|
71
|
|
|
} |
|
72
|
|
|
|
|
73
|
|
|
/** |
|
74
|
|
|
* Destroy the image. |
|
75
|
|
|
*/ |
|
76
|
|
|
public function __destruct() |
|
77
|
|
|
{ |
|
78
|
|
|
imagedestroy($this->image); |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* {@inheritdoc} |
|
83
|
|
|
*/ |
|
84
|
|
|
public function flip() |
|
85
|
|
|
{ |
|
86
|
|
|
imageflip($this->image, IMG_FLIP_VERTICAL); |
|
87
|
|
|
} |
|
88
|
|
|
|
|
89
|
|
|
/** |
|
90
|
|
|
* {@inheritdoc} |
|
91
|
|
|
*/ |
|
92
|
|
|
public function flop() |
|
93
|
|
|
{ |
|
94
|
|
|
imageflip($this->image, IMG_FLIP_HORIZONTAL); |
|
95
|
|
|
} |
|
96
|
|
|
|
|
97
|
|
|
/** |
|
98
|
|
|
* {@inheritdoc} |
|
99
|
|
|
*/ |
|
100
|
|
|
public function save($filename) |
|
101
|
|
|
{ |
|
102
|
|
|
$extension = image_type_to_extension($this->type, false); |
|
103
|
|
|
$function = 'image'.$extension; |
|
104
|
|
|
|
|
105
|
|
|
if (!function_exists($function) || ($function($this->image, $filename) === false)) { |
|
106
|
|
|
throw new ImageException("The image format '{$extension}' cannot be saved to '{$filename}'"); |
|
107
|
|
|
} |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
/** |
|
111
|
|
|
* {@inheritdoc} |
|
112
|
|
|
*/ |
|
113
|
|
|
public function getString() |
|
114
|
|
|
{ |
|
115
|
|
|
$extension = image_type_to_extension($this->type, false); |
|
116
|
|
|
$function = 'image'.$extension; |
|
117
|
|
|
|
|
118
|
|
|
if (!function_exists($function)) { |
|
119
|
|
|
throw new ImageException("The image format '{$extension}' cannot be exported"); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
ob_start(); |
|
123
|
|
|
|
|
124
|
|
|
if ($extension === 'jpeg') { |
|
125
|
|
|
$function($this->image, null, $this->quality); |
|
126
|
|
|
} else { |
|
127
|
|
|
$function($this->image); |
|
128
|
|
|
} |
|
129
|
|
|
|
|
130
|
|
|
return ob_get_clean(); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* {@inheritdoc} |
|
135
|
|
|
*/ |
|
136
|
|
|
public function getMimeType() |
|
137
|
|
|
{ |
|
138
|
|
|
return image_type_to_mime_type($this->type); |
|
139
|
|
|
} |
|
140
|
|
|
|
|
141
|
|
|
/** |
|
142
|
|
|
* {@inheritdoc} |
|
143
|
|
|
*/ |
|
144
|
|
|
public function getWidth() |
|
145
|
|
|
{ |
|
146
|
|
|
return imagesx($this->image); |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
/** |
|
150
|
|
|
* {@inheritdoc} |
|
151
|
|
|
*/ |
|
152
|
|
|
public function getHeight() |
|
153
|
|
|
{ |
|
154
|
|
|
return imagesy($this->image); |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
|
|
* {@inheritdoc} |
|
159
|
|
|
*/ |
|
160
|
|
|
public function format($format) |
|
161
|
|
|
{ |
|
162
|
|
|
switch (strtolower($format)) { |
|
163
|
|
|
case 'jpg': |
|
164
|
|
|
case 'jpeg': |
|
165
|
|
|
$width = $this->getWidth(); |
|
166
|
|
|
$height = $this->getHeight(); |
|
167
|
|
|
|
|
168
|
|
|
if (($image = imagecreatetruecolor($width, $height)) === false) { |
|
169
|
|
|
throw new ImageException('Error creating a image'); |
|
170
|
|
|
} |
|
171
|
|
|
|
|
172
|
|
|
if (imagesavealpha($image, true) === false) { |
|
173
|
|
|
throw new ImageException('Error saving the alpha chanel of the image'); |
|
174
|
|
|
} |
|
175
|
|
|
|
|
176
|
|
|
if (isset($background[3])) { |
|
|
|
|
|
|
177
|
|
|
$background = imagecolorallocatealpha($image, $background[0], $background[1], $background[2], $background[3]); |
|
178
|
|
|
} else { |
|
179
|
|
|
$background = imagecolorallocate($image, $background[0], $background[1], $background[2]); |
|
|
|
|
|
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
if (imagefill($image, 0, 0, $background) === false) { |
|
183
|
|
|
throw new ImageException('Error filling the image'); |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
imagecopy($image, $this->image, 0, 0, 0, 0, $width, $height); |
|
187
|
|
|
|
|
188
|
|
|
$this->image = $image; |
|
189
|
|
|
$this->type = IMAGETYPE_JPEG; |
|
190
|
|
|
break; |
|
191
|
|
|
|
|
192
|
|
|
case 'gif': |
|
193
|
|
|
$this->type = IMAGETYPE_GIF; |
|
194
|
|
|
break; |
|
195
|
|
|
|
|
196
|
|
|
case 'png': |
|
197
|
|
|
$this->type = IMAGETYPE_PNG; |
|
198
|
|
|
break; |
|
199
|
|
|
|
|
200
|
|
|
default: |
|
201
|
|
|
throw new ImageException("The image format '{$format}' is not valid"); |
|
202
|
|
|
} |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
/** |
|
206
|
|
|
* {@inheritdoc} |
|
207
|
|
|
*/ |
|
208
|
|
|
public function resize($width, $height) |
|
209
|
|
|
{ |
|
210
|
|
|
if (($image = imagescale($this->image, $width, $height, IMG_BICUBIC)) === false) { |
|
211
|
|
|
throw new ImageException('Error resizing the image'); |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
$this->image = $image; |
|
215
|
|
|
} |
|
216
|
|
|
|
|
217
|
|
|
/** |
|
218
|
|
|
* {@inheritdoc} |
|
219
|
|
|
*/ |
|
220
|
|
|
public function getCropOffsets($width, $height, $method) |
|
221
|
|
|
{ |
|
222
|
|
|
if (isset(static::$fallbackCropMethods[$method])) { |
|
223
|
|
|
return static::$fallbackCropMethods[$method]; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
throw new ImageException("The crop method '$method' is not available for Gd"); |
|
227
|
|
|
} |
|
228
|
|
|
|
|
229
|
|
|
/** |
|
230
|
|
|
* {@inheritdoc} |
|
231
|
|
|
*/ |
|
232
|
|
|
public function crop($width, $height, $x, $y) |
|
233
|
|
|
{ |
|
234
|
|
|
$crop = [ |
|
235
|
|
|
'width' => $width, |
|
236
|
|
|
'height' => $height, |
|
237
|
|
|
'x' => $x, |
|
238
|
|
|
'y' => $y, |
|
239
|
|
|
]; |
|
240
|
|
|
|
|
241
|
|
|
if (($image = imagecrop($this->image, $crop)) === false) { |
|
242
|
|
|
throw new ImageException('Error cropping the image'); |
|
243
|
|
|
} |
|
244
|
|
|
|
|
245
|
|
|
$this->image = $image; |
|
246
|
|
|
} |
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* {@inheritdoc} |
|
250
|
|
|
*/ |
|
251
|
|
|
public function rotate($angle) |
|
252
|
|
|
{ |
|
253
|
|
|
$background = imagecolorallocatealpha($this->image, 0, 0, 0, 127); |
|
254
|
|
|
|
|
255
|
|
|
if ($background === false || ($image = imagerotate($this->image, $angle, $background)) === false) { |
|
256
|
|
|
throw new ImageException('Error rotating the image'); |
|
257
|
|
|
} |
|
258
|
|
|
|
|
259
|
|
|
$this->image = $image; |
|
260
|
|
|
} |
|
261
|
|
|
} |
|
262
|
|
|
|
This check marks calls to
isset(...)orempty(...)that are found before the variable itself is defined. These will always have the same result.This is likely the result of code being shifted around. Consider removing these calls.