1 <?php
2
3 4 5 6 7 8 9 10 11 12
13 class Image_GD_Driver extends Image_Driver {
14
15
16 protected static $blank_png;
17 protected static $blank_png_width;
18 protected static $blank_png_height;
19
20 public function __construct()
21 {
22
23 if ( ! function_exists('gd_info'))
24 throw new CException('image gd requires v2');
25
26
27 $info = gd_info();
28
29
30 if (strpos($info['GD Version'], '2.') === FALSE)
31 throw new CException('image gd requires v2');
32 }
33
34 public function process($image, $actions, $dir, $file, $render = FALSE)
35 {
36
37 switch ($image['type'])
38 {
39 case IMAGETYPE_JPEG:
40 $create = 'imagecreatefromjpeg';
41 break;
42 case IMAGETYPE_GIF:
43 $create = 'imagecreatefromgif';
44 break;
45 case IMAGETYPE_PNG:
46 $create = 'imagecreatefrompng';
47 break;
48 }
49
50
51 switch (strtolower(substr(strrchr($file, '.'), 1)))
52 {
53 case 'jpg':
54 case 'jpeg':
55 $save = 'imagejpeg';
56 break;
57 case 'gif':
58 $save = 'imagegif';
59 break;
60 case 'png':
61 $save = 'imagepng';
62 break;
63 }
64
65
66 if (empty($create) OR ! function_exists($create))
67 throw new CException('image type not allowed');
68
69
70 if (empty($save) OR ! function_exists($save))
71 throw new CException('image type not allowed');
72
73
74 $this->image = $image;
75
76
77 $this->tmp_image = $create($image['file']);
78
79
80 if(isset ($actions['quality'])) {
81 $quality = $actions['quality'];
82 unset($actions['quality']);
83 }
84
85 if ($status = $this->execute($actions))
86 {
87
88 imagealphablending($this->tmp_image, TRUE);
89 imagesavealpha($this->tmp_image, TRUE);
90
91 switch ($save)
92 {
93 case 'imagejpeg':
94
95 ($quality === NULL) and $quality = 95;
96 break;
97 case 'imagegif':
98
99 unset($quality);
100 break;
101 case 'imagepng':
102
103
104 $quality = 9;
105 break;
106 }
107
108 if ($render === FALSE)
109 {
110
111 $status = isset($quality) ? $save($this->tmp_image, $dir.$file, $quality) : $save($this->tmp_image, $dir.$file);
112 }
113 else
114 {
115
116 switch ($save)
117 {
118 case 'imagejpeg':
119 header('Content-Type: image/jpeg');
120 break;
121 case 'imagegif':
122 header('Content-Type: image/gif');
123 break;
124 case 'imagepng':
125 header('Content-Type: image/png');
126 break;
127 }
128
129 $status = isset($quality) ? $save($this->tmp_image, NULL, $quality) : $save($this->tmp_image);
130 }
131
132
133 imagedestroy($this->tmp_image);
134 }
135
136 return $status;
137 }
138
139 public function flip($direction)
140 {
141
142 $width = imagesx($this->tmp_image);
143 $height = imagesy($this->tmp_image);
144
145
146 $flipped = $this->imagecreatetransparent($width, $height);
147
148 if ($direction === Image::HORIZONTAL)
149 {
150 for ($x = 0; $x < $width; $x++)
151 {
152 $status = imagecopy($flipped, $this->tmp_image, $x, 0, $width - $x - 1, 0, 1, $height);
153 }
154 }
155 elseif ($direction === Image::VERTICAL)
156 {
157 for ($y = 0; $y < $height; $y++)
158 {
159 $status = imagecopy($flipped, $this->tmp_image, 0, $y, 0, $height - $y - 1, $width, 1);
160 }
161 }
162 else
163 {
164
165 return TRUE;
166 }
167
168 if ($status === TRUE)
169 {
170
171 imagedestroy($this->tmp_image);
172 $this->tmp_image = $flipped;
173 }
174
175 return $status;
176 }
177
178 public function crop($properties)
179 {
180
181 $this->sanitize_geometry($properties);
182
183
184 $width = imagesx($this->tmp_image);
185 $height = imagesy($this->tmp_image);
186
187
188 $img = $this->imagecreatetransparent($properties['width'], $properties['height']);
189
190
191 if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, $properties['left'], $properties['top'], $width, $height, $width, $height))
192 {
193
194 imagedestroy($this->tmp_image);
195 $this->tmp_image = $img;
196 }
197
198 return $status;
199 }
200
201 public function resize($properties)
202 {
203
204 $width = imagesx($this->tmp_image);
205 $height = imagesy($this->tmp_image);
206
207 if (substr($properties['width'], -1) === '%')
208 {
209
210 $properties['width'] = round($width * (substr($properties['width'], 0, -1) / 100));
211 }
212
213 if (substr($properties['height'], -1) === '%')
214 {
215
216 $properties['height'] = round($height * (substr($properties['height'], 0, -1) / 100));
217 }
218
219
220 empty($properties['width']) and $properties['width'] = round($width * $properties['height'] / $height);
221 empty($properties['height']) and $properties['height'] = round($height * $properties['width'] / $width);
222
223 if ($properties['master'] === Image::AUTO)
224 {
225
226 $properties['master'] = (($width / $properties['width']) > ($height / $properties['height'])) ? Image::WIDTH : Image::HEIGHT;
227 }
228
229 if (empty($properties['height']) OR $properties['master'] === Image::WIDTH)
230 {
231
232 $properties['height'] = round($height * $properties['width'] / $width);
233 }
234
235 if (empty($properties['width']) OR $properties['master'] === Image::HEIGHT)
236 {
237
238 $properties['width'] = round($width * $properties['height'] / $height);
239 }
240
241
242 if ($properties['width'] > $width / 2 AND $properties['height'] > $height / 2)
243 {
244
245 $pre_width = $width;
246 $pre_height = $height;
247
248
249 $max_reduction_width = round($properties['width'] * 1.1);
250 $max_reduction_height = round($properties['height'] * 1.1);
251
252
253 while ($pre_width / 2 > $max_reduction_width AND $pre_height / 2 > $max_reduction_height)
254 {
255 $pre_width /= 2;
256 $pre_height /= 2;
257 }
258
259
260 $img = $this->imagecreatetransparent($pre_width, $pre_height);
261
262 if ($status = imagecopyresized($img, $this->tmp_image, 0, 0, 0, 0, $pre_width, $pre_height, $width, $height))
263 {
264
265 imagedestroy($this->tmp_image);
266 $this->tmp_image = $img;
267 }
268
269
270 $width = $pre_width;
271 $height = $pre_height;
272 }
273
274
275 $img = $this->imagecreatetransparent($properties['width'], $properties['height']);
276
277
278 if ($status = imagecopyresampled($img, $this->tmp_image, 0, 0, 0, 0, $properties['width'], $properties['height'], $width, $height))
279 {
280
281 imagedestroy($this->tmp_image);
282 $this->tmp_image = $img;
283 }
284
285 return $status;
286 }
287
288 public function rotate($amount)
289 {
290
291 $img = $this->tmp_image;
292
293
294 $transparent = imagecolorallocatealpha($img, 255, 255, 255, 127);
295
296
297 $img = imagerotate($img, 360 - $amount, $transparent, -1);
298
299
300 imagecolortransparent($img, $transparent);
301
302
303 if ($status = imagecopymerge($this->tmp_image, $img, 0, 0, 0, 0, imagesx($this->tmp_image), imagesy($this->tmp_image), 100))
304 {
305
306 imagealphablending($img, TRUE);
307 imagesavealpha($img, TRUE);
308
309
310 imagedestroy($this->tmp_image);
311 $this->tmp_image = $img;
312 }
313
314 return $status;
315 }
316
317 public function sharpen($amount)
318 {
319
320 if ( ! function_exists('imageconvolution'))
321 throw new CException('image unsupported method');
322
323
324 $amount = round(abs(-18 + ($amount * 0.08)), 2);
325
326
327 $matrix = array
328 (
329 array(-1, -1, -1),
330 array(-1, $amount, -1),
331 array(-1, -1, -1),
332 );
333
334
335 return imageconvolution($this->tmp_image, $matrix, $amount - 8, 0);
336 }
337
338 protected function properties()
339 {
340 return array(imagesx($this->tmp_image), imagesy($this->tmp_image));
341 }
342
343 344 345 346 347 348 349 350
351 protected function imagecreatetransparent($width, $height)
352 {
353 if (self::$blank_png === NULL)
354 {
355
356 self::$blank_png = imagecreatefromstring(base64_decode
357 (
358 'iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29'.
359 'mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAADqSURBVHjaYvz//z/DYAYAAcTEMMgBQAANegcCBN'.
360 'CgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQ'.
361 'AANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoH'.
362 'AgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAAA16BwIE0KB'.
363 '3IEAADXoHAgTQoHcgQAANegcCBNCgdyBAgAEAMpcDTTQWJVEAAAAASUVORK5CYII='
364 ));
365
366
367 self::$blank_png_width = imagesx(self::$blank_png);
368 self::$blank_png_height = imagesy(self::$blank_png);
369 }
370
371 $img = imagecreatetruecolor($width, $height);
372
373
374 imagecopyresized($img, self::$blank_png, 0, 0, 0, 0, $width, $height, self::$blank_png_width, self::$blank_png_height);
375
376
377 imagealphablending($img, FALSE);
378 imagesavealpha($img, TRUE);
379
380 return $img;
381 }
382
383 }