1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* Methods used with the {@link resize()} method. |
5
|
|
|
*/ |
6
|
|
|
define('ZEBRA_IMAGE_BOXED', 0); |
7
|
|
|
define('ZEBRA_IMAGE_NOT_BOXED', 1); |
8
|
|
|
define('ZEBRA_IMAGE_CROP_TOPLEFT', 2); |
9
|
|
|
define('ZEBRA_IMAGE_CROP_TOPCENTER', 3); |
10
|
|
|
define('ZEBRA_IMAGE_CROP_TOPRIGHT', 4); |
11
|
|
|
define('ZEBRA_IMAGE_CROP_MIDDLELEFT', 5); |
12
|
|
|
define('ZEBRA_IMAGE_CROP_CENTER', 6); |
13
|
|
|
define('ZEBRA_IMAGE_CROP_MIDDLERIGHT', 7); |
14
|
|
|
define('ZEBRA_IMAGE_CROP_BOTTOMLEFT', 8); |
15
|
|
|
define('ZEBRA_IMAGE_CROP_BOTTOMCENTER', 9); |
16
|
|
|
define('ZEBRA_IMAGE_CROP_BOTTOMRIGHT', 10); |
17
|
|
|
|
18
|
|
|
// this enables handling of partially broken JPEG files without warnings/errors |
19
|
|
|
ini_set('gd.jpeg_ignore_warning', true); |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* A compact, lightweight, object-oriented image manipulation library written in and for PHP, that provides methods |
23
|
|
|
* for performing several types of image manipulation operations. It doesn't require any external libraries other than |
24
|
|
|
* the GD2 extension (with which PHP usually comes precompiled with). |
25
|
|
|
* |
26
|
|
|
* The code is heavily commented and generates no warnings/errors/notices when PHP's error reporting level is set to |
27
|
|
|
* E_ALL. |
28
|
|
|
* |
29
|
|
|
* With this library you can rescale, flip, rotate and crop images. It supports loading and saving images in the GIF, |
30
|
|
|
* JPEG and PNG formats and preserves transparency for GIF, PNG and PNG24. |
31
|
|
|
* |
32
|
|
|
* The cool thing about it is that it can resize images to exact given width and height and still maintain aspect |
33
|
|
|
* ratio. |
34
|
|
|
* |
35
|
|
|
* Visit {@link http://stefangabos.ro/php-libraries/zebra-image/} for more information. |
36
|
|
|
* |
37
|
|
|
* For more resources visit {@link http://stefangabos.ro/} |
38
|
|
|
* |
39
|
|
|
* @author Stefan Gabos <[email protected]> |
40
|
|
|
* @version 2.2.3 (last revision: July 14, 2013) |
41
|
|
|
* @copyright (c) 2006 - 2013 Stefan Gabos |
42
|
|
|
* @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE |
43
|
|
|
* @package Zebra_Image |
44
|
|
|
*/ |
45
|
|
|
class Zebra_Image |
|
|
|
|
46
|
|
|
{ |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Indicates the file system permissions to be set for newly created images. |
50
|
|
|
* |
51
|
|
|
* Better is to leave this setting as it is. |
52
|
|
|
* |
53
|
|
|
* If you know what you are doing, here is how you can calculate the permission levels: |
54
|
|
|
* |
55
|
|
|
* - 400 Owner Read |
56
|
|
|
* - 200 Owner Write |
57
|
|
|
* - 100 Owner Execute |
58
|
|
|
* - 40 Group Read |
59
|
|
|
* - 20 Group Write |
60
|
|
|
* - 10 Group Execute |
61
|
|
|
* - 4 Global Read |
62
|
|
|
* - 2 Global Write |
63
|
|
|
* - 1 Global Execute |
64
|
|
|
* |
65
|
|
|
* Default is 0755 |
66
|
|
|
* |
67
|
|
|
* @var integer |
68
|
|
|
*/ |
69
|
|
|
public $chmod_value; |
70
|
|
|
|
71
|
|
|
/** |
72
|
|
|
* If set to FALSE, images having both width and height smaller than the required width and height, will be left |
73
|
|
|
* untouched ({@link jpeg_quality} and {@link png_compression} will still apply). |
74
|
|
|
* |
75
|
|
|
* Available only for the {@link resize()} method |
76
|
|
|
* |
77
|
|
|
* Default is TRUE |
78
|
|
|
* |
79
|
|
|
* @var boolean |
80
|
|
|
*/ |
81
|
|
|
public $enlarge_smaller_images; |
82
|
|
|
|
83
|
|
|
/** |
84
|
|
|
* In case of an error read this property's value to see the error's code. |
85
|
|
|
* |
86
|
|
|
* Possible error codes are: |
87
|
|
|
* |
88
|
|
|
* - 1: source file could not be found |
89
|
|
|
* - 2: source file is not readable |
90
|
|
|
* - 3: could not write target file |
91
|
|
|
* - 4: unsupported source file format |
92
|
|
|
* - 5: unsupported target file format |
93
|
|
|
* - 6: GD library version does not support target file format |
94
|
|
|
* - 7: GD library is not installed! |
95
|
|
|
* - 8: "chmod" command is disabled via configuration |
96
|
|
|
* |
97
|
|
|
* Default is 0 (no error). |
98
|
|
|
* |
99
|
|
|
* @var integer |
100
|
|
|
*/ |
101
|
|
|
public $error; |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Indicates the quality of the output image (better quality means bigger file size). |
105
|
|
|
* |
106
|
|
|
* Used only if the file at {@link target_path} is a JPG/JPEG image. |
107
|
|
|
* |
108
|
|
|
* Range is 0 - 100 |
109
|
|
|
* |
110
|
|
|
* Default is 85 |
111
|
|
|
* |
112
|
|
|
* @var integer |
113
|
|
|
*/ |
114
|
|
|
public $jpeg_quality; |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* Indicates the compression level of the output image (lower compression means bigger file size). |
118
|
|
|
* |
119
|
|
|
* Available only if PHP version is 5.1.2+, and only if the file at {@link target_path} is a PNG image. It will be |
120
|
|
|
* ignored otherwise. |
121
|
|
|
* |
122
|
|
|
* Range is 0 - 9 |
123
|
|
|
* |
124
|
|
|
* Default is 9 |
125
|
|
|
* |
126
|
|
|
* @since 2.2 |
127
|
|
|
* |
128
|
|
|
* @var integer |
129
|
|
|
*/ |
130
|
|
|
public $png_compression; |
131
|
|
|
|
132
|
|
|
/** |
133
|
|
|
* Specifies whether, upon resizing, images should preserve their aspect ratio. |
134
|
|
|
* |
135
|
|
|
* Available only for the {@link resize()} method |
136
|
|
|
* |
137
|
|
|
* Default is TRUE |
138
|
|
|
* |
139
|
|
|
* @var boolean |
140
|
|
|
*/ |
141
|
|
|
public $preserve_aspect_ratio; |
142
|
|
|
|
143
|
|
|
/** |
144
|
|
|
* Indicates whether a target files should preserve the source file's date/time. |
145
|
|
|
* |
146
|
|
|
* Default is TRUE |
147
|
|
|
* |
148
|
|
|
* @since 1.0.4 |
149
|
|
|
* |
150
|
|
|
* @var boolean |
151
|
|
|
*/ |
152
|
|
|
public $preserve_time; |
153
|
|
|
|
154
|
|
|
/** |
155
|
|
|
* Indicates whether the target image should have a "sharpen" filter applied to it. |
156
|
|
|
* |
157
|
|
|
* Can be very useful when creating thumbnails and should be used only when creating thumbnails. |
158
|
|
|
* |
159
|
|
|
* <i>The sharpen filter relies on the "imageconvolution" PHP function which is available only for PHP version |
160
|
|
|
* 5.1.0+, and will leave the images unaltered for older versions!</i> |
161
|
|
|
* |
162
|
|
|
* Default is FALSE |
163
|
|
|
* |
164
|
|
|
* @since 2.2 |
165
|
|
|
* |
166
|
|
|
* @var boolean |
167
|
|
|
*/ |
168
|
|
|
public $sharpen_images; |
169
|
|
|
|
170
|
|
|
/** |
171
|
|
|
* Path to an image file to apply the transformations to. |
172
|
|
|
* |
173
|
|
|
* Supported file types are <b>GIF</b>, <b>PNG</b> and <b>JPEG</b>. |
174
|
|
|
* |
175
|
|
|
* @var string |
176
|
|
|
*/ |
177
|
|
|
public $source_path; |
178
|
|
|
|
179
|
|
|
/** |
180
|
|
|
* Path (including file name) to where to save the transformed image. |
181
|
|
|
* |
182
|
|
|
* <i>Can be a different than {@link source_path} - the type of the transformed image will be as indicated by the |
183
|
|
|
* file's extension (supported file types are GIF, PNG and JPEG)</i>. |
184
|
|
|
* |
185
|
|
|
* @var string |
186
|
|
|
*/ |
187
|
|
|
public $target_path; |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Constructor of the class. |
191
|
|
|
* |
192
|
|
|
* Initializes the class and the default properties |
193
|
|
|
* |
194
|
|
|
* @return void |
|
|
|
|
195
|
|
|
*/ |
196
|
|
|
public function __construct() |
197
|
|
|
{ |
198
|
|
|
|
199
|
|
|
// set default values for properties |
200
|
|
|
$this->chmod_value = 0755; |
201
|
|
|
|
202
|
|
|
$this->error = 0; |
203
|
|
|
|
204
|
|
|
$this->jpeg_quality = 85; |
205
|
|
|
|
206
|
|
|
$this->png_compression = 9; |
207
|
|
|
|
208
|
|
|
$this->preserve_aspect_ratio = $this->preserve_time = $this->enlarge_smaller_images = true; |
209
|
|
|
|
210
|
|
|
$this->sharpen_images = false; |
211
|
|
|
|
212
|
|
|
$this->source_path = $this->target_path = ''; |
213
|
|
|
} |
214
|
|
|
|
215
|
|
|
/** |
216
|
|
|
* Applies one or more filters to the image given as {@link source_path} and outputs it as the file specified as |
217
|
|
|
* {@link target_path}. |
218
|
|
|
* |
219
|
|
|
* <samp>This method is available only if the {@link http://php.net/manual/en/function.imagefilter.php imagefilter} |
220
|
|
|
* function is available (available from PHP 5+), and will leave images unaltered otherwise.</samp> |
221
|
|
|
* |
222
|
|
|
* <code> |
223
|
|
|
* // include the Zebra_Image library |
224
|
|
|
* require 'path/to/Zebra_Image.php'; |
225
|
|
|
* |
226
|
|
|
* // instantiate the class |
227
|
|
|
* $img = new Zebra_Image(); |
228
|
|
|
* |
229
|
|
|
* // a source image |
230
|
|
|
* $img->source_path = 'path/to/source.ext'; |
231
|
|
|
* |
232
|
|
|
* // path to where should the resulting image be saved |
233
|
|
|
* // note that by simply setting a different extension to the file will |
234
|
|
|
* // instruct the script to create an image of that particular type |
235
|
|
|
* $img->target_path = 'path/to/target.ext'; |
236
|
|
|
* |
237
|
|
|
* // apply the "grayscale" filter |
238
|
|
|
* $img->apply_filter('grayscale'); |
239
|
|
|
* |
240
|
|
|
* // apply the "contrast" filter |
241
|
|
|
* $img->apply_filter('contrast', -20); |
242
|
|
|
* </code> |
243
|
|
|
* |
244
|
|
|
* You can also apply multiple filters at once. In this case, the method requires a single argument, an array of |
245
|
|
|
* arrays, containing the filters and associated arguments, where applicable: |
246
|
|
|
* |
247
|
|
|
* <code> |
248
|
|
|
* // create a sepia effect |
249
|
|
|
* // note how we're applying multiple filters at once |
250
|
|
|
* // each filter is in its own array |
251
|
|
|
* $img->apply_filter(array( |
252
|
|
|
* |
253
|
|
|
* // first we apply the "grayscale" filter |
254
|
|
|
* array('grayscale'), |
255
|
|
|
* |
256
|
|
|
* // then we apply the "colorize" filter with 90, 60, 40 as |
257
|
|
|
* // the values for red, green and blue |
258
|
|
|
* array('colorize', 90, 60, 40), |
259
|
|
|
* |
260
|
|
|
* )); |
261
|
|
|
* </code> |
262
|
|
|
* |
263
|
|
|
* @param string $filter The (case-insensitive) name of the filter to apply. Can be one of the following: |
264
|
|
|
* |
265
|
|
|
* - <b>brightness</b> - changes the brightness of the image; use <b>arg1</b> |
266
|
|
|
* to set the level of brightness; the range of brightness |
267
|
|
|
* is -255 to 255; |
268
|
|
|
* - <b>colorize</b> - adds (subtracts) specified RGB values to each pixel; |
269
|
|
|
* use <b>arg1</b>, <b>arg2</b> and <b>arg3</b> in the |
270
|
|
|
* form of red, green, blue and <b>arg4</b> for the alpha |
271
|
|
|
* channel. the range for each color is -255 to 255 and |
272
|
|
|
* 0 to 127 for alpha; <i>alpha support is available only |
273
|
|
|
* for PHP 5.2.5+</i>; |
274
|
|
|
* - <b>contrast</b> - changes the contrast of the image; use <b>arg1</b> |
275
|
|
|
* to set the level of contrast; the range of contrast |
276
|
|
|
* is -100 to 100; |
277
|
|
|
* - <b>gausian_blur</b> - blurs the image using the Gaussian method; |
278
|
|
|
* - <b>grayscale</b> - converts the image into grayscale; |
279
|
|
|
* - <b>edgedetect</b> - uses edge detection to highlight the edges in the image; |
280
|
|
|
* - <b>emboss</b> - embosses the image; |
281
|
|
|
* - <b>mean_removal</b> - uses mean removal to achieve a "sketchy" effect; |
282
|
|
|
* - <b>negate</b> - reverses all the colors of the image; |
283
|
|
|
* - <b>pixelate</b> - applies pixelation effect to the image, use <b>arg1</b> |
284
|
|
|
* to set the block size and <b>arg2</b> to set the |
285
|
|
|
* pixelation effect mode; <i>this filter is available |
286
|
|
|
* only for PHP 5.3.0+</i>; |
287
|
|
|
* - <b>selective_blur</b> - blurs the image; |
288
|
|
|
* - <b>smooth</b> - makes the image smoother. Use <b>arg1</b> to set the |
289
|
|
|
* level of smoothness. applies a 9-cell convolution matrix |
290
|
|
|
* where center pixel has the weight of <b>arg1</b> and |
291
|
|
|
* others weight of 1.0. the result is normalized by dividing |
292
|
|
|
* the sum with <b>arg1</b> + 8.0 (sum of the matrix). |
293
|
|
|
* any float is accepted; |
294
|
|
|
* |
295
|
|
|
* @param mixed $arg1 Used by the following filters: |
296
|
|
|
* - <b>brightness</b> - sets the brightness level (-255 to 255) |
297
|
|
|
* - <b>contrast</b> - sets the contrast level (-100 to 100) |
298
|
|
|
* - <b>colorize</b> - sets the value of the red component (-255 to 255) |
299
|
|
|
* - <b>smooth</b> - sets the smoothness level |
300
|
|
|
* - <b>pixelate</b> - sets the block size, in pixels |
301
|
|
|
* |
302
|
|
|
* @param mixed $arg2 Used by the following filters: |
303
|
|
|
* - <b>colorize</b> - sets the value of the green component (-255 to 255) |
304
|
|
|
* - <b>pixelate</b> - whether to use advanced pixelation effect or not (defaults to FALSE). |
305
|
|
|
* |
306
|
|
|
* @param mixed $arg3 Used by the following filters: |
307
|
|
|
* - <b>colorize</b> - sets the value of the blue component (-255 to 255) |
308
|
|
|
* |
309
|
|
|
* @param mixed $arg4 Used by the following filters: |
310
|
|
|
* - <b>colorize</b> - alpha channel; a value between 0 and 127. 0 indicates |
311
|
|
|
* completely opaque while 127 indicates completely |
312
|
|
|
* transparent. |
313
|
|
|
* |
314
|
|
|
* @since 2.2.2 |
315
|
|
|
* |
316
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
317
|
|
|
* |
318
|
|
|
* If {@link http://php.net/manual/en/function.imagefilter.php imagefilter} is not |
319
|
|
|
* available the method will return FALSE without setting an {@link error} code. |
320
|
|
|
* |
321
|
|
|
* If the requested filter doesn't exist, or invalid arguments are passed, the method |
322
|
|
|
* will trigger a warning. |
323
|
|
|
* |
324
|
|
|
* If FALSE is returned and you are sure that |
325
|
|
|
* {@link http://php.net/manual/en/function.imagefilter.php imagefilter} exists and that |
326
|
|
|
* the requested filter is valid, check the {@link error} property to see the error code. |
327
|
|
|
*/ |
328
|
|
|
public function apply_filter($filter, $arg1 = '', $arg2 = '', $arg3 = '', $arg4 = '') |
|
|
|
|
329
|
|
|
{ |
330
|
|
|
|
331
|
|
|
// if "imagefilter" function exists and the requested filter exists |
332
|
|
|
if (function_exists('imagefilter')) { // if image resource was successfully created |
333
|
|
|
if ($this->_create_from_source()) { |
334
|
|
|
|
335
|
|
|
// prepare the target image |
336
|
|
|
$target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1); |
|
|
|
|
337
|
|
|
|
338
|
|
|
// copy the original image |
339
|
|
|
imagecopyresampled( |
340
|
|
|
|
341
|
|
|
$target_identifier, $this->source_identifier, 0, 0, 0, 0, $this->source_width, $this->source_height, $this->source_width, $this->source_height |
|
|
|
|
342
|
|
|
|
343
|
|
|
); |
344
|
|
|
|
345
|
|
|
// if multiple filters are to be applied at once |
346
|
|
|
if (is_array($filter)) { |
347
|
|
|
|
348
|
|
|
// iterate through the filters |
349
|
|
|
foreach ($filter as $arguments) { // if filter exists |
350
|
|
|
if (defined('IMG_FILTER_' . strtoupper($arguments[0]))) { |
351
|
|
|
|
352
|
|
|
// try to apply the filter... |
353
|
|
View Code Duplication |
if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($arguments[0]))), array_slice($arguments, 1)))) { |
|
|
|
|
354
|
|
|
// ...and trigger an error if the filter could not be applied |
355
|
|
|
|
356
|
|
|
trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING); |
357
|
|
|
} |
358
|
|
|
|
359
|
|
|
// if filter doesn't exists, trigger an error |
360
|
|
|
} else { |
361
|
|
|
trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING); |
362
|
|
|
} |
363
|
|
|
} |
364
|
|
|
|
365
|
|
|
// if a single filter is to be applied and it is available |
366
|
|
|
} elseif (defined('IMG_FILTER_' . strtoupper($filter))) { |
367
|
|
|
|
368
|
|
|
// get all the arguments passed to the method |
369
|
|
|
$arguments = func_get_args(); |
370
|
|
|
|
371
|
|
|
// try to apply the filter... |
372
|
|
View Code Duplication |
if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($filter))), array_slice($arguments, 1)))) { |
|
|
|
|
373
|
|
|
// ...and trigger an error if the filter could not be applied |
374
|
|
|
|
375
|
|
|
trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING); |
376
|
|
|
} |
377
|
|
|
|
378
|
|
|
// if filter doesn't exists, trigger an error |
379
|
|
|
} else { |
380
|
|
|
trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING); |
|
|
|
|
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
// write image |
384
|
|
|
return $this->_write_image($target_identifier); |
385
|
|
|
} |
386
|
|
|
} |
387
|
|
|
|
388
|
|
|
// if script gets this far, return false |
389
|
|
|
// note that we do not set the error level as it has been already set |
390
|
|
|
// by the _create_from_source() method earlier, if the case |
391
|
|
|
return false; |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
/** |
395
|
|
|
* Crops a portion of the image given as {@link source_path} and outputs it as the file specified as {@link target_path}. |
396
|
|
|
* |
397
|
|
|
* <code> |
398
|
|
|
* // include the Zebra_Image library |
399
|
|
|
* require 'path/to/Zebra_Image.php'; |
400
|
|
|
* |
401
|
|
|
* // instantiate the class |
402
|
|
|
* $img = new Zebra_Image(); |
403
|
|
|
* |
404
|
|
|
* // a source image |
405
|
|
|
* $img->source_path = 'path/to/source.ext'; |
406
|
|
|
* |
407
|
|
|
* // path to where should the resulting image be saved |
408
|
|
|
* // note that by simply setting a different extension to the file will |
409
|
|
|
* // instruct the script to create an image of that particular type |
410
|
|
|
* $img->target_path = 'path/to/target.ext'; |
411
|
|
|
* |
412
|
|
|
* // crop a rectangle of 100x100 pixels, starting from the top-left corner |
413
|
|
|
* $img->crop(0, 0, 100, 100); |
414
|
|
|
* </code> |
415
|
|
|
* |
416
|
|
|
* @param integer $start_x x coordinate to start cropping from |
417
|
|
|
* |
418
|
|
|
* @param integer $start_y y coordinate to start cropping from |
419
|
|
|
* |
420
|
|
|
* @param integer $end_x x coordinate where to end the cropping |
421
|
|
|
* |
422
|
|
|
* @param integer $end_y y coordinate where to end the cropping |
423
|
|
|
* |
424
|
|
|
* @since 1.0.4 |
425
|
|
|
* |
426
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
427
|
|
|
* |
428
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
429
|
|
|
*/ |
430
|
|
|
public function crop($start_x, $start_y, $end_x, $end_y) |
431
|
|
|
{ |
432
|
|
|
|
433
|
|
|
// this method might be also called internally |
434
|
|
|
// in this case, there's a fifth argument that points to an already existing image identifier |
435
|
|
|
$args = func_get_args(); |
436
|
|
|
|
437
|
|
|
// if fifth argument exists |
438
|
|
|
if (isset($args[4]) && is_resource($args[4])) { |
439
|
|
|
|
440
|
|
|
// that it is the image identifier that we'll be using further on |
441
|
|
|
$this->source_identifier = $args[4]; |
442
|
|
|
|
443
|
|
|
// set this to true so that the script will continue to execute at the next IF |
444
|
|
|
$result = true; |
445
|
|
|
|
446
|
|
|
// if method is called as usually |
447
|
|
|
// try to create an image resource from source path |
448
|
|
|
} else { |
449
|
|
|
$result = $this->_create_from_source(); |
450
|
|
|
} |
451
|
|
|
|
452
|
|
|
// if image resource was successfully created |
453
|
|
|
if ($result !== false) { |
454
|
|
|
|
455
|
|
|
// prepare the target image |
456
|
|
|
$target_identifier = $this->_prepare_image($end_x - $start_x, $end_y - $start_y, -1); |
457
|
|
|
|
458
|
|
|
// crop the image |
459
|
|
|
imagecopyresampled( |
460
|
|
|
|
461
|
|
|
$target_identifier, $this->source_identifier, 0, 0, $start_x, $start_y, $end_x - $start_x, $end_y - $start_y, $end_x - $start_x, $end_y - $start_y |
462
|
|
|
|
463
|
|
|
); |
464
|
|
|
|
465
|
|
|
// write image |
466
|
|
|
return $this->_write_image($target_identifier); |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
// if script gets this far, return false |
470
|
|
|
// note that we do not set the error level as it has been already set |
471
|
|
|
// by the _create_from_source() method earlier |
472
|
|
|
return false; |
473
|
|
|
} |
474
|
|
|
|
475
|
|
|
/** |
476
|
|
|
* Flips both horizontally and vertically the image given as {@link source_path} and outputs the resulted image as |
477
|
|
|
* {@link target_path} |
478
|
|
|
* |
479
|
|
|
* <code> |
480
|
|
|
* // include the Zebra_Image library |
481
|
|
|
* require 'path/to/Zebra_Image.php'; |
482
|
|
|
* |
483
|
|
|
* // instantiate the class |
484
|
|
|
* $img = new Zebra_Image(); |
485
|
|
|
* |
486
|
|
|
* // a source image |
487
|
|
|
* $img->source_path = 'path/to/source.ext'; |
488
|
|
|
* |
489
|
|
|
* // path to where should the resulting image be saved |
490
|
|
|
* // note that by simply setting a different extension to the file will |
491
|
|
|
* // instruct the script to create an image of that particular type |
492
|
|
|
* $img->target_path = 'path/to/target.ext'; |
493
|
|
|
* |
494
|
|
|
* // flip the image both horizontally and vertically |
495
|
|
|
* $img->flip_both(); |
496
|
|
|
* </code> |
497
|
|
|
* |
498
|
|
|
* @since 2.1 |
499
|
|
|
* |
500
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
501
|
|
|
* |
502
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
503
|
|
|
*/ |
504
|
|
|
public function flip_both() |
505
|
|
|
{ |
506
|
|
|
return $this->_flip('both'); |
507
|
|
|
} |
508
|
|
|
|
509
|
|
|
/** |
510
|
|
|
* Flips horizontally the image given as {@link source_path} and outputs the resulted image as {@link target_path} |
511
|
|
|
* |
512
|
|
|
* <code> |
513
|
|
|
* // include the Zebra_Image library |
514
|
|
|
* require 'path/to/Zebra_Image.php'; |
515
|
|
|
* |
516
|
|
|
* // instantiate the class |
517
|
|
|
* $img = new Zebra_Image(); |
518
|
|
|
* |
519
|
|
|
* // a source image |
520
|
|
|
* $img->source_path = 'path/to/source.ext'; |
521
|
|
|
* |
522
|
|
|
* // path to where should the resulting image be saved |
523
|
|
|
* // note that by simply setting a different extension to the file will |
524
|
|
|
* // instruct the script to create an image of that particular type |
525
|
|
|
* $img->target_path = 'path/to/target.ext'; |
526
|
|
|
* |
527
|
|
|
* // flip the image horizontally |
528
|
|
|
* $img->flip_horizontal(); |
529
|
|
|
* </code> |
530
|
|
|
* |
531
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
532
|
|
|
* |
533
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
534
|
|
|
*/ |
535
|
|
|
public function flip_horizontal() |
536
|
|
|
{ |
537
|
|
|
return $this->_flip('horizontal'); |
538
|
|
|
} |
539
|
|
|
|
540
|
|
|
/** |
541
|
|
|
* Flips vertically the image given as {@link source_path} and outputs the resulted image as {@link target_path} |
542
|
|
|
* |
543
|
|
|
* <code> |
544
|
|
|
* // include the Zebra_Image library |
545
|
|
|
* require 'path/to/Zebra_Image.php'; |
546
|
|
|
* |
547
|
|
|
* // instantiate the class |
548
|
|
|
* $img = new Zebra_Image(); |
549
|
|
|
* |
550
|
|
|
* // a source image |
551
|
|
|
* $img->source_path = 'path/to/source.ext'; |
552
|
|
|
* |
553
|
|
|
* // path to where should the resulting image be saved |
554
|
|
|
* // note that by simply setting a different extension to the file will |
555
|
|
|
* // instruct the script to create an image of that particular type |
556
|
|
|
* $img->target_path = 'path/to/target.ext'; |
557
|
|
|
* |
558
|
|
|
* // flip the image vertically |
559
|
|
|
* $img->flip_vertical(); |
560
|
|
|
* </code> |
561
|
|
|
* |
562
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
563
|
|
|
* |
564
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
565
|
|
|
*/ |
566
|
|
|
public function flip_vertical() |
567
|
|
|
{ |
568
|
|
|
return $this->_flip('vertical'); |
569
|
|
|
} |
570
|
|
|
|
571
|
|
|
/** |
572
|
|
|
* Resizes the image given as {@link source_path} and outputs the resulted image as {@link target_path}. |
573
|
|
|
* |
574
|
|
|
* <code> |
575
|
|
|
* // include the Zebra_Image library |
576
|
|
|
* require 'path/to/Zebra_Image.php'; |
577
|
|
|
* |
578
|
|
|
* // instantiate the class |
579
|
|
|
* $img = new Zebra_Image(); |
580
|
|
|
* |
581
|
|
|
* // a source image |
582
|
|
|
* $img->source_path = 'path/to/source.ext'; |
583
|
|
|
* |
584
|
|
|
* // path to where should the resulting image be saved |
585
|
|
|
* // note that by simply setting a different extension to the file will |
586
|
|
|
* // instruct the script to create an image of that particular type |
587
|
|
|
* $img->target_path = 'path/to/target.ext'; |
588
|
|
|
* |
589
|
|
|
* // apply a "sharpen" filter to the resulting images |
590
|
|
|
* $img->sharpen_images = true; |
591
|
|
|
* |
592
|
|
|
* // resize the image to exactly 150x150 pixels, without altering aspect ratio, by using the CROP_CENTER method |
593
|
|
|
* $img->resize(150, 150, ZEBRA_IMAGE_CROP_CENTER); |
594
|
|
|
* </code> |
595
|
|
|
* |
596
|
|
|
* @param integer $width The width to resize the image to. |
597
|
|
|
* |
598
|
|
|
* If set to <b>0</b>, the width will be automatically adjusted, depending |
599
|
|
|
* on the value of the <b>height</b> argument so that the image preserves |
600
|
|
|
* its aspect ratio. |
601
|
|
|
* |
602
|
|
|
* If {@link preserve_aspect_ratio} is set to TRUE and both this and the |
603
|
|
|
* <b>height</b> arguments are values greater than <b>0</b>, the image will |
604
|
|
|
* be resized to the exact required width and height and the aspect ratio |
605
|
|
|
* will be preserved - (also see the description for the <b>method</b> |
606
|
|
|
* argument below on how can this be done). |
607
|
|
|
* |
608
|
|
|
* If {@link preserve_aspect_ratio} is set to FALSE, the image will be |
609
|
|
|
* resized to the required width and the aspect ratio will be ignored. |
610
|
|
|
* |
611
|
|
|
* If both <b>width</b> and <b>height</b> are set to <b>0</b>, a copy of |
612
|
|
|
* the source image will be created ({@link jpeg_quality} and |
613
|
|
|
* {@link png_compression} will still apply). |
614
|
|
|
* |
615
|
|
|
* If either <b>width</b> or <b>height</b> are set to <b>0</b>, the script |
616
|
|
|
* will consider the value of the {@link preserve_aspect_ratio} to bet set |
617
|
|
|
* to TRUE regardless of its actual value! |
618
|
|
|
* |
619
|
|
|
* @param integer $height The height to resize the image to. |
620
|
|
|
* |
621
|
|
|
* If set to <b>0</b>, the height will be automatically adjusted, depending |
622
|
|
|
* on the value of the <b>width</b> argument so that the image preserves |
623
|
|
|
* its aspect ratio. |
624
|
|
|
* |
625
|
|
|
* If {@link preserve_aspect_ratio} is set to TRUE and both this and the |
626
|
|
|
* <b>width</b> arguments are values greater than <b>0</b>, the image will |
627
|
|
|
* be resized to the exact required width and height and the aspect ratio |
628
|
|
|
* will be preserved - (also see the description for the <b>method</b> |
629
|
|
|
* argument below on how can this be done). |
630
|
|
|
* |
631
|
|
|
* If {@link preserve_aspect_ratio} is set to FALSE, the image will be |
632
|
|
|
* resized to the required height and the aspect ratio will be ignored. |
633
|
|
|
* |
634
|
|
|
* If both <b>width</b> and <b>height</b> are set to <b>0</b>, a copy of |
635
|
|
|
* the source image will be created ({@link jpeg_quality} and |
636
|
|
|
* {@link png_compression} will still apply). |
637
|
|
|
* |
638
|
|
|
* If either <b>height</b> or <b>width</b> are set to <b>0</b>, the script |
639
|
|
|
* will consider the value of the {@link preserve_aspect_ratio} to bet set |
640
|
|
|
* to TRUE regardless of its actual value! |
641
|
|
|
* |
642
|
|
|
* @param int $method (Optional) Method to use when resizing images to exact width and height |
643
|
|
|
* while preserving aspect ratio. |
644
|
|
|
* |
645
|
|
|
* If the {@link preserve_aspect_ratio} property is set to TRUE and both the |
646
|
|
|
* <b>width</b> and <b>height</b> arguments are values greater than <b>0</b>, |
647
|
|
|
* the image will be resized to the exact given width and height and the |
648
|
|
|
* aspect ratio will be preserved by using on of the following methods: |
649
|
|
|
* |
650
|
|
|
* - <b>ZEBRA_IMAGE_BOXED</b> - the image will be scalled so that it will |
651
|
|
|
* fit in a box with the given width and height (both width/height will |
652
|
|
|
* be smaller or equal to the required width/height) and then it will |
653
|
|
|
* be centered both horizontally and vertically. The blank area will be |
654
|
|
|
* filled with the color specified by the <b>bgcolor</b> argument. (the |
655
|
|
|
* blank area will be filled only if the image is not transparent!) |
656
|
|
|
* |
657
|
|
|
* - <b>ZEBRA_IMAGE_NOT_BOXED</b> - the image will be scalled so that it |
658
|
|
|
* <i>could</i> fit in a box with the given width and height but will |
659
|
|
|
* not be enclosed in a box with given width and height. The new width/ |
660
|
|
|
* height will be both smaller or equal to the required width/height |
661
|
|
|
* |
662
|
|
|
* - <b>ZEBRA_IMAGE_CROP_TOPLEFT</b> |
663
|
|
|
* - <b>ZEBRA_IMAGE_CROP_TOPCENTER</b> |
664
|
|
|
* - <b>ZEBRA_IMAGE_CROP_TOPRIGHT</b> |
665
|
|
|
* - <b>ZEBRA_IMAGE_CROP_MIDDLELEFT</b> |
666
|
|
|
* - <b>ZEBRA_IMAGE_CROP_CENTER</b> |
667
|
|
|
* - <b>ZEBRA_IMAGE_CROP_MIDDLERIGHT</b> |
668
|
|
|
* - <b>ZEBRA_IMAGE_CROP_BOTTOMLEFT</b> |
669
|
|
|
* - <b>ZEBRA_IMAGE_CROP_BOTTOMCENTER</b> |
670
|
|
|
* - <b>ZEBRA_IMAGE_CROP_BOTTOMRIGHT</b> |
671
|
|
|
* |
672
|
|
|
* For the methods involving crop, first the image is scaled so that both |
673
|
|
|
* its sides are equal or greater than the respective sizes of the bounding |
674
|
|
|
* box; next, a region of required width and height will be cropped from |
675
|
|
|
* indicated region of the resulted image. |
676
|
|
|
* |
677
|
|
|
* Default is ZEBRA_IMAGE_CROP_CENTER |
678
|
|
|
* |
679
|
|
|
* @param \hexadecimal|string $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the |
680
|
|
|
* blank area. See the <b>method</b> argument. |
681
|
|
|
* |
682
|
|
|
* When set to -1 the script will preserve transparency for transparent GIF |
683
|
|
|
* and PNG images. For non-transparent images the background will be white |
684
|
|
|
* in this case. |
685
|
|
|
* |
686
|
|
|
* Default is #FFFFFF. |
687
|
|
|
* |
688
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
689
|
|
|
* |
690
|
|
|
* If FALSE is returned, check the {@link error} property to see what went |
691
|
|
|
* wrong |
692
|
|
|
*/ |
693
|
|
|
public function resize($width = 0, $height = 0, $method = ZEBRA_IMAGE_CROP_CENTER, $background_color = '#FFFFFF') |
694
|
|
|
{ |
695
|
|
|
|
696
|
|
|
// if image resource was successfully created |
697
|
|
|
if ($this->_create_from_source()) { |
698
|
|
|
|
699
|
|
|
// if either width or height is to be adjusted automatically |
700
|
|
|
// set a flag telling the script that, even if $preserve_aspect_ratio is set to false |
701
|
|
|
// treat everything as if it was set to true |
702
|
|
|
if ($width == 0 || $height == 0) { |
703
|
|
|
$auto_preserve_aspect_ratio = true; |
704
|
|
|
} |
705
|
|
|
|
706
|
|
|
// if aspect ratio needs to be preserved |
707
|
|
|
if ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) { |
708
|
|
|
|
709
|
|
|
// if height is given and width is to be computed accordingly |
710
|
|
|
if ($width == 0 && $height > 0) { |
711
|
|
|
|
712
|
|
|
// get the original image's aspect ratio |
713
|
|
|
$aspect_ratio = $this->source_width / $this->source_height; |
714
|
|
|
|
715
|
|
|
// the target image's height is as given as argument to the method |
716
|
|
|
$target_height = $height; |
717
|
|
|
|
718
|
|
|
// compute the target image's width, preserving the aspect ratio |
719
|
|
|
$target_width = round($height * $aspect_ratio); |
720
|
|
|
|
721
|
|
|
// if width is given and height is to be computed accordingly |
722
|
|
|
} elseif ($width > 0 && $height == 0) { |
723
|
|
|
|
724
|
|
|
// get the original image's aspect ratio |
725
|
|
|
$aspect_ratio = $this->source_height / $this->source_width; |
726
|
|
|
|
727
|
|
|
// the target image's width is as given as argument to the method |
728
|
|
|
$target_width = $width; |
729
|
|
|
|
730
|
|
|
// compute the target image's height, preserving the aspect ratio |
731
|
|
|
$target_height = round($width * $aspect_ratio); |
732
|
|
|
|
733
|
|
|
// if both width and height are given and ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED methods are to be used |
734
|
|
|
} elseif ($width > 0 && $height > 0 && ($method == 0 || $method == 1)) { |
735
|
|
|
|
736
|
|
|
// compute the horizontal and vertical aspect ratios |
737
|
|
|
$vertical_aspect_ratio = $height / $this->source_height; |
738
|
|
|
$horizontal_aspect_ratio = $width / $this->source_width; |
739
|
|
|
|
740
|
|
|
// if the image's newly computed height would be inside the bounding box |
741
|
|
|
if (round($horizontal_aspect_ratio * $this->source_height < $height)) { |
742
|
|
|
|
743
|
|
|
// the target image's width is as given as argument to the method |
744
|
|
|
$target_width = $width; |
745
|
|
|
|
746
|
|
|
// compute the target image's height so that the image will stay inside the bounding box |
747
|
|
|
$target_height = round($horizontal_aspect_ratio * $this->source_height); |
748
|
|
|
|
749
|
|
|
// otherwise |
750
|
|
|
} else { |
751
|
|
|
|
752
|
|
|
// the target image's height is as given as argument to the method |
753
|
|
|
$target_height = $height; |
754
|
|
|
|
755
|
|
|
// compute the target image's width so that the image will stay inside the bounding box |
756
|
|
|
$target_width = round($vertical_aspect_ratio * $this->source_width); |
757
|
|
|
} |
758
|
|
|
|
759
|
|
|
// if both width and height are given and image is to be cropped in order to get to the required size |
760
|
|
|
} elseif ($width > 0 && $height > 0 && $method > 1 && $method < 11) { |
761
|
|
|
|
762
|
|
|
// compute the horizontal and vertical aspect ratios |
763
|
|
|
$vertical_aspect_ratio = $this->source_height / $height; |
764
|
|
|
$horizontal_aspect_ratio = $this->source_width / $width; |
765
|
|
|
|
766
|
|
|
// we'll use one of the two |
767
|
|
|
$aspect_ratio = $vertical_aspect_ratio < $horizontal_aspect_ratio ? |
768
|
|
|
|
769
|
|
|
$vertical_aspect_ratio : |
770
|
|
|
|
771
|
|
|
$horizontal_aspect_ratio; |
772
|
|
|
|
773
|
|
|
// compute the target image's width, preserving the aspect ratio |
774
|
|
|
$target_width = round($this->source_width / $aspect_ratio); |
775
|
|
|
|
776
|
|
|
// compute the target image's height, preserving the aspect ratio |
777
|
|
|
$target_height = round($this->source_height / $aspect_ratio); |
778
|
|
|
|
779
|
|
|
// for any other case |
780
|
|
|
} else { |
781
|
|
|
|
782
|
|
|
// we will create a copy of the source image |
783
|
|
|
$target_width = $this->source_width; |
784
|
|
|
$target_height = $this->source_height; |
785
|
|
|
} |
786
|
|
|
|
787
|
|
|
// if aspect ratio does not need to be preserved |
788
|
|
|
} else { |
789
|
|
|
|
790
|
|
|
// compute the target image's width |
791
|
|
|
$target_width = ($width > 0 ? $width : $this->source_width); |
792
|
|
|
|
793
|
|
|
// compute the target image's height |
794
|
|
|
$target_height = ($height > 0 ? $height : $this->source_height); |
795
|
|
|
} |
796
|
|
|
|
797
|
|
|
// if |
798
|
|
|
if ( |
799
|
|
|
|
800
|
|
|
// all images are to be resized - including images that are smaller than the given width/height |
801
|
|
|
$this->enlarge_smaller_images || // smaller images than the given width/height are to be left untouched |
802
|
|
|
// but current image has at leas one side that is larger than the required width/height |
803
|
|
|
($width > 0 && $height > 0 ? |
804
|
|
|
|
805
|
|
|
($this->source_width > $width || $this->source_height > $height) : |
806
|
|
|
|
807
|
|
|
($this->source_width > $target_width || $this->source_height > $target_height) |
808
|
|
|
|
809
|
|
|
) |
810
|
|
|
|
811
|
|
|
) { |
812
|
|
|
|
813
|
|
|
// if |
814
|
|
|
if ( |
815
|
|
|
|
816
|
|
|
// aspect ratio needs to be preserved AND |
817
|
|
|
($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) && // both width and height are given |
818
|
|
|
($width > 0 && $height > 0) && // images are to be cropped |
819
|
|
|
($method > 1 && $method < 11) |
820
|
|
|
|
821
|
|
|
) { |
822
|
|
|
|
823
|
|
|
// prepare the target image |
824
|
|
|
$target_identifier = $this->_prepare_image($target_width, $target_height, $background_color); |
825
|
|
|
|
826
|
|
|
imagecopyresampled( |
827
|
|
|
|
828
|
|
|
$target_identifier, $this->source_identifier, 0, 0, 0, 0, $target_width, $target_height, $this->source_width, $this->source_height |
829
|
|
|
|
830
|
|
|
); |
831
|
|
|
|
832
|
|
|
// do the crop according to the required method |
833
|
|
|
switch ($method) { |
834
|
|
|
|
835
|
|
|
// if image needs to be cropped from the top-left corner |
836
|
|
|
case ZEBRA_IMAGE_CROP_TOPLEFT: |
|
|
|
|
837
|
|
|
|
838
|
|
|
// crop accordingly |
839
|
|
|
return $this->crop(0, 0, $width, $height, $target_identifier // crop this resource instead |
840
|
|
|
); |
841
|
|
|
|
842
|
|
|
break; |
|
|
|
|
843
|
|
|
|
844
|
|
|
// if image needs to be cropped from the top-center |
845
|
|
View Code Duplication |
case ZEBRA_IMAGE_CROP_TOPCENTER: |
|
|
|
|
846
|
|
|
|
847
|
|
|
// crop accordingly |
848
|
|
|
return $this->crop(floor(($target_width - $width) / 2), 0, floor(($target_width - $width) / 2) + $width, $height, $target_identifier // crop this resource instead |
849
|
|
|
); |
850
|
|
|
|
851
|
|
|
break; |
|
|
|
|
852
|
|
|
|
853
|
|
|
// if image needs to be cropped from the top-right corner |
854
|
|
|
case ZEBRA_IMAGE_CROP_TOPRIGHT: |
|
|
|
|
855
|
|
|
|
856
|
|
|
// crop accordingly |
857
|
|
|
return $this->crop($target_width - $width, 0, $target_width, $height, $target_identifier // crop this resource instead |
858
|
|
|
); |
859
|
|
|
|
860
|
|
|
break; |
|
|
|
|
861
|
|
|
|
862
|
|
|
// if image needs to be cropped from the middle-left |
863
|
|
View Code Duplication |
case ZEBRA_IMAGE_CROP_MIDDLELEFT: |
|
|
|
|
864
|
|
|
|
865
|
|
|
// crop accordingly |
866
|
|
|
return $this->crop( |
867
|
|
|
|
868
|
|
|
0, floor(($target_height - $height) / 2), $width, floor(($target_height - $height) / 2) + $height, $target_identifier // crop this resource instead |
869
|
|
|
|
870
|
|
|
); |
871
|
|
|
|
872
|
|
|
break; |
|
|
|
|
873
|
|
|
|
874
|
|
|
// if image needs to be cropped from the center of the image |
875
|
|
|
case ZEBRA_IMAGE_CROP_CENTER: |
|
|
|
|
876
|
|
|
|
877
|
|
|
// crop accordingly |
878
|
|
|
return $this->crop( |
879
|
|
|
|
880
|
|
|
floor(($target_width - $width) / 2), floor(($target_height - $height) / 2), floor(($target_width - $width) / 2) + $width, floor(($target_height - $height) / 2) + $height, $target_identifier // crop this resource instead |
881
|
|
|
|
882
|
|
|
); |
883
|
|
|
|
884
|
|
|
break; |
|
|
|
|
885
|
|
|
|
886
|
|
|
// if image needs to be cropped from the middle-right |
887
|
|
View Code Duplication |
case ZEBRA_IMAGE_CROP_MIDDLERIGHT: |
|
|
|
|
888
|
|
|
|
889
|
|
|
// crop accordingly |
890
|
|
|
return $this->crop( |
891
|
|
|
|
892
|
|
|
$target_width - $width, floor(($target_height - $height) / 2), $target_width, floor(($target_height - $height) / 2) + $height, $target_identifier // crop this resource instead |
893
|
|
|
|
894
|
|
|
); |
895
|
|
|
|
896
|
|
|
break; |
|
|
|
|
897
|
|
|
|
898
|
|
|
// if image needs to be cropped from the bottom-left corner |
899
|
|
|
case ZEBRA_IMAGE_CROP_BOTTOMLEFT: |
|
|
|
|
900
|
|
|
|
901
|
|
|
// crop accordingly |
902
|
|
|
return $this->crop( |
903
|
|
|
|
904
|
|
|
0, $target_height - $height, $width, $target_height, $target_identifier // crop this resource instead |
905
|
|
|
|
906
|
|
|
); |
907
|
|
|
|
908
|
|
|
break; |
|
|
|
|
909
|
|
|
|
910
|
|
|
// if image needs to be cropped from the bottom-center |
911
|
|
View Code Duplication |
case ZEBRA_IMAGE_CROP_BOTTOMCENTER: |
|
|
|
|
912
|
|
|
|
913
|
|
|
// crop accordingly |
914
|
|
|
return $this->crop( |
915
|
|
|
|
916
|
|
|
floor(($target_width - $width) / 2), $target_height - $height, floor(($target_width - $width) / 2) + $width, $target_height, $target_identifier // crop this resource instead |
917
|
|
|
|
918
|
|
|
); |
919
|
|
|
|
920
|
|
|
break; |
|
|
|
|
921
|
|
|
|
922
|
|
|
// if image needs to be cropped from the bottom-right corner |
923
|
|
|
case ZEBRA_IMAGE_CROP_BOTTOMRIGHT: |
|
|
|
|
924
|
|
|
|
925
|
|
|
// crop accordingly |
926
|
|
|
return $this->crop( |
927
|
|
|
|
928
|
|
|
$target_width - $width, $target_height - $height, $target_width, $target_height, $target_identifier // crop this resource instead |
929
|
|
|
|
930
|
|
|
); |
931
|
|
|
|
932
|
|
|
break; |
|
|
|
|
933
|
|
|
|
934
|
|
|
} |
935
|
|
|
|
936
|
|
|
// if aspect ratio doesn't need to be preserved or |
937
|
|
|
// it needs to be preserved and method is ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED |
938
|
|
|
} else { |
939
|
|
|
|
940
|
|
|
// prepare the target image |
941
|
|
|
$target_identifier = $this->_prepare_image(($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $width : $target_width), ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $height : $target_height), $background_color); |
942
|
|
|
|
943
|
|
|
imagecopyresampled( |
944
|
|
|
|
945
|
|
|
$target_identifier, $this->source_identifier, ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($width - $target_width) / 2 : 0), ($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($height - $target_height) / 2 : 0), 0, 0, $target_width, $target_height, $this->source_width, $this->source_height |
946
|
|
|
|
947
|
|
|
); |
948
|
|
|
|
949
|
|
|
// if script gets this far, write the image to disk |
950
|
|
|
return $this->_write_image($target_identifier); |
951
|
|
|
} |
952
|
|
|
|
953
|
|
|
// if we get here it means that |
954
|
|
|
// smaller images than the given width/height are to be left untouched |
955
|
|
|
// therefore, we save the image as it is |
956
|
|
|
} else { |
957
|
|
|
return $this->_write_image($this->source_identifier); |
958
|
|
|
} |
959
|
|
|
} |
960
|
|
|
|
961
|
|
|
// if script gets this far return false |
962
|
|
|
// note that we do not set the error level as it has been already set |
963
|
|
|
// by the _create_from_source() method earlier |
964
|
|
|
return false; |
965
|
|
|
} |
966
|
|
|
|
967
|
|
|
/** |
968
|
|
|
* Rotates the image given as {@link source_path} and outputs the resulted image as {@link target_path}. |
969
|
|
|
* |
970
|
|
|
* <code> |
971
|
|
|
* // include the Zebra_Image library |
972
|
|
|
* require 'path/to/Zebra_Image.php'; |
973
|
|
|
* |
974
|
|
|
* // instantiate the class |
975
|
|
|
* $img = new Zebra_Image(); |
976
|
|
|
* |
977
|
|
|
* // a source image |
978
|
|
|
* $img->source_path = 'path/to/source.ext'; |
979
|
|
|
* |
980
|
|
|
* // path to where should the resulting image be saved |
981
|
|
|
* // note that by simply setting a different extension to the file will |
982
|
|
|
* // instruct the script to create an image of that particular type |
983
|
|
|
* $img->target_path = 'path/to/target.ext'; |
984
|
|
|
* |
985
|
|
|
* // rotate the image 45 degrees, clockwise |
986
|
|
|
* $img->rotate(45); |
987
|
|
|
* </code> |
988
|
|
|
* |
989
|
|
|
* @param double $angle Angle by which to rotate the image clockwise. |
990
|
|
|
* |
991
|
|
|
* Between 0 and 360. |
992
|
|
|
* |
993
|
|
|
* @param mixed $background_color (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the |
994
|
|
|
* uncovered zone after the rotation. |
995
|
|
|
* |
996
|
|
|
* When set to -1 the script will preserve transparency for transparent GIF |
997
|
|
|
* and PNG images. For non-transparent images the background will be white |
998
|
|
|
* in this case. |
999
|
|
|
* |
1000
|
|
|
* Default is -1. |
1001
|
|
|
* |
1002
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
1003
|
|
|
* |
1004
|
|
|
* If FALSE is returned, check the {@link error} property to see the error |
1005
|
|
|
* code. |
1006
|
|
|
*/ |
1007
|
|
|
public function rotate($angle, $background_color = -1) |
1008
|
|
|
{ |
1009
|
|
|
|
1010
|
|
|
// if image resource was successfully created |
1011
|
|
|
if ($this->_create_from_source()) { |
1012
|
|
|
|
1013
|
|
|
// angles are given clockwise but imagerotate works counterclockwise so we need to negate our value |
1014
|
|
|
$angle = -$angle; |
1015
|
|
|
|
1016
|
|
|
// if source image is PNG |
1017
|
|
|
if ($this->source_type == IMAGETYPE_PNG && $background_color == -1) { |
1018
|
|
|
|
1019
|
|
|
// rotate the image |
1020
|
|
|
// but if using -1 as background color didn't work (as is the case for PNG8) |
1021
|
|
|
if (!($target_identifier = imagerotate($this->source_identifier, $angle, -1))) { |
1022
|
|
|
|
1023
|
|
|
// we will be using #FFF as the color to fill the uncovered zone after the rotation |
1024
|
|
|
$background_color = imagefilledarc($this->source_identifier, 255, 255, 255); |
1025
|
|
|
|
1026
|
|
|
// rotate the image |
1027
|
|
|
$target_identifier = imagerotate($this->source_identifier, $angle, $background_color); |
1028
|
|
|
} |
1029
|
|
|
|
1030
|
|
|
// if source image is a transparent GIF |
1031
|
|
|
} elseif ($this->source_type == IMAGETYPE_GIF && $this->source_transparent_color_index >= 0) { |
|
|
|
|
1032
|
|
|
|
1033
|
|
|
// convert the background color to RGB values |
1034
|
|
|
$background_color = $this->_hex2rgb($background_color); |
1035
|
|
|
|
1036
|
|
|
// allocate the color to the image identifier |
1037
|
|
|
$background_color = imagefilledarc( |
1038
|
|
|
|
1039
|
|
|
$this->source_identifier, $background_color['r'], $background_color['g'], $background_color['b'] |
1040
|
|
|
|
1041
|
|
|
); |
1042
|
|
|
|
1043
|
|
|
// rotate the image |
1044
|
|
|
$this->source_identifier = imagerotate($this->source_identifier, $angle, $background_color); |
1045
|
|
|
|
1046
|
|
|
// get the width of rotated image |
1047
|
|
|
$width = imagesx($this->source_identifier); |
1048
|
|
|
|
1049
|
|
|
// get the height of rotated image |
1050
|
|
|
$height = imagesy($this->source_identifier); |
1051
|
|
|
|
1052
|
|
|
// create a blank image with the new width and height |
1053
|
|
|
// (this intermediary step is for preserving transparency) |
1054
|
|
|
$target_identifier = $this->_prepare_image($width, $height, -1); |
1055
|
|
|
|
1056
|
|
|
// copy the rotated image on to the new one |
1057
|
|
|
imagecopyresampled($target_identifier, $this->source_identifier, 0, 0, 0, 0, $width, $height, $width, $height); |
1058
|
|
|
|
1059
|
|
|
// for the other cases |
1060
|
|
|
} else { |
1061
|
|
|
|
1062
|
|
|
// convert the color to RGB values |
1063
|
|
|
$background_color = $this->_hex2rgb($background_color); |
1064
|
|
|
|
1065
|
|
|
// allocate the color to the image identifier |
1066
|
|
|
$background_color = imagefilledarc( |
1067
|
|
|
|
1068
|
|
|
$this->source_identifier, $background_color['r'], $background_color['g'], $background_color['b'] |
1069
|
|
|
|
1070
|
|
|
); |
1071
|
|
|
|
1072
|
|
|
// rotate the image |
1073
|
|
|
$target_identifier = imagerotate($this->source_identifier, $angle, $background_color); |
1074
|
|
|
} |
1075
|
|
|
|
1076
|
|
|
// write image |
1077
|
|
|
$this->_write_image($target_identifier); |
1078
|
|
|
} |
1079
|
|
|
|
1080
|
|
|
// if script gets this far return false |
1081
|
|
|
// note that we do not set the error level as it has been already set |
1082
|
|
|
// by the _create_from_source() method earlier |
1083
|
|
|
return false; |
1084
|
|
|
} |
1085
|
|
|
|
1086
|
|
|
/** |
1087
|
|
|
* Returns an array containing the image identifier representing the image obtained from {@link $source_path}, the |
1088
|
|
|
* image's width and height and the image's type |
1089
|
|
|
* |
1090
|
|
|
* @access private |
1091
|
|
|
*/ |
1092
|
|
|
public function _create_from_source() |
1093
|
|
|
{ |
1094
|
|
|
|
1095
|
|
|
// perform some error checking first |
1096
|
|
|
// if the GD library is not installed |
1097
|
|
|
if (!function_exists('gd_info')) { |
1098
|
|
|
|
1099
|
|
|
// save the error level and stop the execution of the script |
1100
|
|
|
$this->error = 7; |
1101
|
|
|
|
1102
|
|
|
return false; |
1103
|
|
|
|
1104
|
|
|
// if source file does not exist |
1105
|
|
|
} elseif (!is_file($this->source_path)) { |
1106
|
|
|
|
1107
|
|
|
// save the error level and stop the execution of the script |
1108
|
|
|
$this->error = 1; |
1109
|
|
|
|
1110
|
|
|
return false; |
1111
|
|
|
|
1112
|
|
|
// if source file is not readable |
1113
|
|
|
} elseif (!is_readable($this->source_path)) { |
1114
|
|
|
|
1115
|
|
|
// save the error level and stop the execution of the script |
1116
|
|
|
$this->error = 2; |
1117
|
|
|
|
1118
|
|
|
return false; |
1119
|
|
|
|
1120
|
|
|
// if target file is same as source file and source file is not writable |
1121
|
|
|
} elseif ($this->target_path == $this->source_path && !is_writable($this->source_path)) { |
1122
|
|
|
|
1123
|
|
|
// save the error level and stop the execution of the script |
1124
|
|
|
$this->error = 3; |
1125
|
|
|
|
1126
|
|
|
return false; |
1127
|
|
|
|
1128
|
|
|
// try to get source file width, height and type |
1129
|
|
|
// and if it founds an unsupported file type |
1130
|
|
|
} elseif (!list($this->source_width, $this->source_height, $this->source_type) = @getimagesize($this->source_path)) { |
1131
|
|
|
|
1132
|
|
|
// save the error level and stop the execution of the script |
1133
|
|
|
$this->error = 4; |
1134
|
|
|
|
1135
|
|
|
return false; |
1136
|
|
|
|
1137
|
|
|
// if no errors so far |
1138
|
|
|
} else { |
1139
|
|
|
|
1140
|
|
|
// get target file's type based on the file extension |
1141
|
|
|
$this->target_type = strtolower(substr($this->target_path, strrpos($this->target_path, '.') + 1)); |
|
|
|
|
1142
|
|
|
|
1143
|
|
|
// create an image from file using extension dependant function |
1144
|
|
|
// checks for file extension |
1145
|
|
|
switch ($this->source_type) { |
1146
|
|
|
|
1147
|
|
|
// if GIF |
1148
|
|
|
case IMAGETYPE_GIF: |
|
|
|
|
1149
|
|
|
|
1150
|
|
|
// create an image from file |
1151
|
|
|
$identifier = imagecreatefromgif($this->source_path); |
1152
|
|
|
|
1153
|
|
|
// get the index of the transparent color (if any) |
1154
|
|
|
if (($this->source_transparent_color_index = imagecolortransparent($identifier)) >= 0) { |
1155
|
|
|
// get the transparent color's RGB values |
1156
|
|
|
// we have to mute errors because there are GIF images which *are* transparent and everything |
1157
|
|
|
// works as expected, but imagecolortransparent() returns a color that is outside the range of |
1158
|
|
|
// colors in the image's pallette... |
1159
|
|
|
|
1160
|
|
|
$this->source_transparent_color = @imagecolorsforindex($identifier, $this->source_transparent_color_index); |
|
|
|
|
1161
|
|
|
} |
1162
|
|
|
|
1163
|
|
|
break; |
1164
|
|
|
|
1165
|
|
|
// if JPEG |
1166
|
|
|
case IMAGETYPE_JPEG: |
|
|
|
|
1167
|
|
|
|
1168
|
|
|
// create an image from file |
1169
|
|
|
$identifier = imagecreatefromjpeg($this->source_path); |
1170
|
|
|
|
1171
|
|
|
break; |
1172
|
|
|
|
1173
|
|
|
// if PNG |
1174
|
|
|
case IMAGETYPE_PNG: |
|
|
|
|
1175
|
|
|
|
1176
|
|
|
// create an image from file |
1177
|
|
|
$identifier = imagecreatefrompng($this->source_path); |
1178
|
|
|
|
1179
|
|
|
// disable blending |
1180
|
|
|
imagealphablending($identifier, false); |
1181
|
|
|
|
1182
|
|
|
break; |
1183
|
|
|
|
1184
|
|
|
default: |
|
|
|
|
1185
|
|
|
|
1186
|
|
|
// if unsupported file type |
1187
|
|
|
// note that we call this if the file is not GIF, JPG or PNG even though the getimagesize function |
1188
|
|
|
// handles more image types |
1189
|
|
|
$this->error = 4; |
1190
|
|
|
|
1191
|
|
|
return false; |
1192
|
|
|
|
1193
|
|
|
} |
1194
|
|
|
} |
1195
|
|
|
|
1196
|
|
|
// if target file has to have the same timestamp as the source image |
1197
|
|
|
// save it as a global property of the class |
1198
|
|
|
if ($this->preserve_time) { |
1199
|
|
|
$this->source_image_time = filemtime($this->source_path); |
|
|
|
|
1200
|
|
|
} |
1201
|
|
|
|
1202
|
|
|
// make available the source image's identifier |
1203
|
|
|
$this->source_identifier = $identifier; |
1204
|
|
|
|
1205
|
|
|
return true; |
1206
|
|
|
} |
1207
|
|
|
|
1208
|
|
|
/** |
1209
|
|
|
* Converts a hexadecimal representation of a color (i.e. #123456 or #AAA) to a RGB representation. |
1210
|
|
|
* |
1211
|
|
|
* The RGB values will be a value between 0 and 255 each. |
1212
|
|
|
* |
1213
|
|
|
* @param string $color Hexadecimal representation of a color (i.e. #123456 or #AAA). |
1214
|
|
|
* |
1215
|
|
|
* @param string $default_on_error Hexadecimal representation of a color to be used in case $color is not |
1216
|
|
|
* recognized as a hexadecimal color. |
1217
|
|
|
* |
1218
|
|
|
* @return array Returns an associative array with the values of (R)ed, (G)reen and (B)lue |
1219
|
|
|
* |
1220
|
|
|
* @access private |
1221
|
|
|
*/ |
1222
|
|
|
public function _hex2rgb($color, $default_on_error = '#FFFFFF') |
1223
|
|
|
{ |
1224
|
|
|
|
1225
|
|
|
// if color is not formatted correctly |
1226
|
|
|
// use the default color |
1227
|
|
|
if (preg_match('/^#?([a-f]|[0-9]){3}(([a-f]|[0-9]){3})?$/i', $color) == 0) { |
1228
|
|
|
$color = $default_on_error; |
1229
|
|
|
} |
1230
|
|
|
|
1231
|
|
|
// trim off the "#" prefix from $background_color |
1232
|
|
|
$color = ltrim($color, '#'); |
1233
|
|
|
|
1234
|
|
|
// if color is given using the shorthand (i.e. "FFF" instead of "FFFFFF") |
1235
|
|
|
if (strlen($color) == 3) { |
1236
|
|
|
$tmp = ''; |
1237
|
|
|
|
1238
|
|
|
// take each value |
1239
|
|
|
// and duplicate it |
1240
|
|
|
for ($i = 0; $i < 3; ++$i) { |
1241
|
|
|
$tmp .= str_repeat($color[$i], 2); |
1242
|
|
|
} |
1243
|
|
|
|
1244
|
|
|
// the color in it's full, 6 characters length notation |
1245
|
|
|
$color = $tmp; |
1246
|
|
|
} |
1247
|
|
|
|
1248
|
|
|
// decimal representation of the color |
1249
|
|
|
$int = hexdec($color); |
1250
|
|
|
|
1251
|
|
|
// extract and return the RGB values |
1252
|
|
|
return array( |
1253
|
|
|
|
1254
|
|
|
'r' => 0xFF & ($int >> 0x10), |
1255
|
|
|
'g' => 0xFF & ($int >> 0x8), |
1256
|
|
|
'b' => 0xFF & $int |
1257
|
|
|
|
1258
|
|
|
); |
1259
|
|
|
} |
1260
|
|
|
|
1261
|
|
|
/** |
1262
|
|
|
* Flips horizontally or vertically or both ways the image given as {@link source_path}. |
1263
|
|
|
* |
1264
|
|
|
* @since 2.1 |
1265
|
|
|
* |
1266
|
|
|
* @access private |
1267
|
|
|
* |
1268
|
|
|
* @param $orientation |
1269
|
|
|
* |
1270
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
1271
|
|
|
* |
1272
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
1273
|
|
|
*/ |
1274
|
|
|
public function _flip($orientation) |
1275
|
|
|
{ |
1276
|
|
|
|
1277
|
|
|
// if image resource was successfully created |
1278
|
|
|
if ($this->_create_from_source()) { |
1279
|
|
|
|
1280
|
|
|
// prepare the target image |
1281
|
|
|
$target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1); |
1282
|
|
|
|
1283
|
|
|
// flip according to $orientation |
1284
|
|
|
switch ($orientation) { |
1285
|
|
|
|
1286
|
|
View Code Duplication |
case 'horizontal': |
|
|
|
|
1287
|
|
|
|
1288
|
|
|
imagecopyresampled( |
1289
|
|
|
|
1290
|
|
|
$target_identifier, $this->source_identifier, 0, 0, $this->source_width - 1, 0, $this->source_width, $this->source_height, -$this->source_width, $this->source_height |
1291
|
|
|
|
1292
|
|
|
); |
1293
|
|
|
|
1294
|
|
|
break; |
1295
|
|
|
|
1296
|
|
View Code Duplication |
case 'vertical': |
|
|
|
|
1297
|
|
|
|
1298
|
|
|
imagecopyresampled( |
1299
|
|
|
|
1300
|
|
|
$target_identifier, $this->source_identifier, 0, 0, 0, $this->source_height - 1, $this->source_width, $this->source_height, $this->source_width, -$this->source_height |
1301
|
|
|
|
1302
|
|
|
); |
1303
|
|
|
|
1304
|
|
|
break; |
1305
|
|
|
|
1306
|
|
View Code Duplication |
case 'both': |
|
|
|
|
1307
|
|
|
|
1308
|
|
|
imagecopyresampled( |
1309
|
|
|
|
1310
|
|
|
$target_identifier, $this->source_identifier, 0, 0, $this->source_width - 1, $this->source_height - 1, $this->source_width, $this->source_height, -$this->source_width, -$this->source_height |
1311
|
|
|
|
1312
|
|
|
); |
1313
|
|
|
|
1314
|
|
|
break; |
1315
|
|
|
|
1316
|
|
|
} |
1317
|
|
|
|
1318
|
|
|
// write image |
1319
|
|
|
return $this->_write_image($target_identifier); |
1320
|
|
|
} |
1321
|
|
|
|
1322
|
|
|
// if script gets this far, return false |
1323
|
|
|
// note that we do not set the error level as it has been already set |
1324
|
|
|
// by the _create_from_source() method earlier |
1325
|
|
|
return false; |
1326
|
|
|
} |
1327
|
|
|
|
1328
|
|
|
/** |
1329
|
|
|
* Creates a blank image of given width, height and background color. |
1330
|
|
|
* |
1331
|
|
|
* @param integer $width Width of the new image. |
1332
|
|
|
* |
1333
|
|
|
* @param integer $height Height of the new image. |
1334
|
|
|
* |
1335
|
|
|
* @param string $background_color (Optional) The hexadecimal color of the background. |
1336
|
|
|
* |
1337
|
|
|
* Can also be -1 case in which the script will try to create a transparent |
1338
|
|
|
* image, if possible. |
1339
|
|
|
* |
1340
|
|
|
* Default is "#FFFFFF". |
1341
|
|
|
* |
1342
|
|
|
* @return Returns the identifier of the newly created image. |
|
|
|
|
1343
|
|
|
* |
1344
|
|
|
* @access private |
1345
|
|
|
*/ |
1346
|
|
|
public function _prepare_image($width, $height, $background_color = '#FFFFFF') |
1347
|
|
|
{ |
1348
|
|
|
|
1349
|
|
|
// create a blank image |
1350
|
|
|
$identifier = imagecreatetruecolor((int)$width <= 0 ? 1 : (int)$width, (int)$height <= 0 ? 1 : (int)$height); |
1351
|
|
|
|
1352
|
|
|
// if we are creating a PNG image |
1353
|
|
|
if ($this->target_type === 'png' && $background_color == -1) { |
1354
|
|
|
|
1355
|
|
|
// disable blending |
1356
|
|
|
imagealphablending($identifier, false); |
1357
|
|
|
|
1358
|
|
|
// allocate a transparent color |
1359
|
|
|
$transparent_color = imagecolorallocatealpha($identifier, 0, 0, 0, 127); |
1360
|
|
|
|
1361
|
|
|
// fill the image with the transparent color |
1362
|
|
|
imagefill($identifier, 0, 0, $transparent_color); |
1363
|
|
|
|
1364
|
|
|
//save full alpha channel information |
1365
|
|
|
imagesavealpha($identifier, true); |
1366
|
|
|
|
1367
|
|
|
// if source image is a transparent GIF |
1368
|
|
|
} elseif ($this->target_type === 'gif' && $background_color == -1 && $this->source_transparent_color_index >= 0) { |
1369
|
|
|
|
1370
|
|
|
// allocate the source image's transparent color also to the new image resource |
1371
|
|
|
$transparent_color = imagefilledarc($identifier, $this->source_transparent_color['red'], $this->source_transparent_color['green'], $this->source_transparent_color['blue']); |
|
|
|
|
1372
|
|
|
|
1373
|
|
|
// fill the background of the new image with transparent color |
1374
|
|
|
imagefill($identifier, 0, 0, $transparent_color); |
1375
|
|
|
|
1376
|
|
|
// from now on, every pixel having the same RGB as the transparent color will be transparent |
1377
|
|
|
imagecolortransparent($identifier, $transparent_color); |
1378
|
|
|
|
1379
|
|
|
// for other image types |
1380
|
|
|
} else { |
1381
|
|
|
|
1382
|
|
|
// if transparent background color specified, revert to white |
1383
|
|
|
if ($background_color == -1) { |
1384
|
|
|
$background_color = '#FFFFFF'; |
1385
|
|
|
} |
1386
|
|
|
|
1387
|
|
|
// convert hex color to rgb |
1388
|
|
|
$background_color = $this->_hex2rgb($background_color); |
1389
|
|
|
|
1390
|
|
|
// prepare the background color |
1391
|
|
|
$background_color = imagefilledarc($identifier, $background_color['r'], $background_color['g'], $background_color['b']); |
1392
|
|
|
|
1393
|
|
|
// fill the image with the background color |
1394
|
|
|
imagefill($identifier, 0, 0, $background_color); |
1395
|
|
|
} |
1396
|
|
|
|
1397
|
|
|
// return the image's identifier |
1398
|
|
|
return $identifier; |
1399
|
|
|
} |
1400
|
|
|
|
1401
|
|
|
/** |
1402
|
|
|
* Sharpens images. Useful when creating thumbnails. |
1403
|
|
|
* |
1404
|
|
|
* Code taken from the comments at {@link http://docs.php.net/imageconvolution}. |
1405
|
|
|
* |
1406
|
|
|
* <i>This function will yield a result only for PHP version 5.1.0+ and will leave the image unaltered for older |
1407
|
|
|
* versions!</i> |
1408
|
|
|
* |
1409
|
|
|
* @param $image |
1410
|
|
|
* |
1411
|
|
|
* @return |
1412
|
|
|
* @internal param \identifier $identifier An image identifier |
1413
|
|
|
* |
1414
|
|
|
* @access private |
1415
|
|
|
*/ |
1416
|
|
|
public function _sharpen_image($image) |
1417
|
|
|
{ |
1418
|
|
|
|
1419
|
|
|
// if the "sharpen_images" is set to true and we're running an appropriate version of PHP |
1420
|
|
|
// (the "imageconvolution" is available only for PHP 5.1.0+) |
1421
|
|
|
if ($this->sharpen_images && version_compare(PHP_VERSION, '5.1.0') >= 0) { |
1422
|
|
|
|
1423
|
|
|
// the convolution matrix as an array of three arrays of three floats |
1424
|
|
|
$matrix = array( |
1425
|
|
|
array(-1.2, -1, -1.2), |
1426
|
|
|
array(-1, 20, -1), |
1427
|
|
|
array(-1.2, -1, -1.2), |
1428
|
|
|
); |
1429
|
|
|
|
1430
|
|
|
// the divisor of the matrix |
1431
|
|
|
$divisor = array_sum(array_map('array_sum', $matrix)); |
1432
|
|
|
|
1433
|
|
|
// color offset |
1434
|
|
|
$offset = 0; |
1435
|
|
|
|
1436
|
|
|
// sharpen image |
1437
|
|
|
imageconvolution($image, $matrix, $divisor, $offset); |
1438
|
|
|
} |
1439
|
|
|
|
1440
|
|
|
// return the image's identifier |
1441
|
|
|
return $image; |
1442
|
|
|
} |
1443
|
|
|
|
1444
|
|
|
/** |
1445
|
|
|
* Creates a new image from given image identifier having the extension as specified by {@link target_path}. |
1446
|
|
|
* |
1447
|
|
|
* @param $identifier identifier An image identifier |
1448
|
|
|
* |
1449
|
|
|
* @return boolean Returns TRUE on success or FALSE on error. |
1450
|
|
|
* |
1451
|
|
|
* If FALSE is returned, check the {@link error} property to see the error code. |
1452
|
|
|
* |
1453
|
|
|
* @access private |
1454
|
|
|
*/ |
1455
|
|
|
public function _write_image($identifier) |
1456
|
|
|
{ |
1457
|
|
|
|
1458
|
|
|
// sharpen image if it's required |
1459
|
|
|
$this->_sharpen_image($identifier); |
1460
|
|
|
|
1461
|
|
|
// image saving process goes according to required extension |
1462
|
|
|
switch ($this->target_type) { |
1463
|
|
|
|
1464
|
|
|
// if GIF |
1465
|
|
|
case 'gif': |
|
|
|
|
1466
|
|
|
|
1467
|
|
|
// if GD support for this file type is not available |
1468
|
|
|
// in version 1.6 of GD the support for GIF files was dropped see |
1469
|
|
|
// http://php.net/manual/en/function.imagegif.php#function.imagegif.notes |
1470
|
|
|
if (!function_exists('imagegif')) { |
1471
|
|
|
|
1472
|
|
|
// save the error level and stop the execution of the script |
1473
|
|
|
$this->error = 6; |
1474
|
|
|
|
1475
|
|
|
return false; |
1476
|
|
|
|
1477
|
|
|
// if, for some reason, file could not be created |
1478
|
|
|
} elseif (@!imagegif($identifier, $this->target_path)) { |
1479
|
|
|
|
1480
|
|
|
// save the error level and stop the execution of the script |
1481
|
|
|
$this->error = 3; |
1482
|
|
|
|
1483
|
|
|
return false; |
1484
|
|
|
} |
1485
|
|
|
|
1486
|
|
|
break; |
1487
|
|
|
|
1488
|
|
|
// if JPEG |
1489
|
|
|
case 'jpg': |
1490
|
|
View Code Duplication |
case 'jpeg': |
|
|
|
|
1491
|
|
|
|
1492
|
|
|
// if GD support for this file type is not available |
1493
|
|
|
if (!function_exists('imagejpeg')) { |
1494
|
|
|
|
1495
|
|
|
// save the error level and stop the execution of the script |
1496
|
|
|
$this->error = 6; |
1497
|
|
|
|
1498
|
|
|
return false; |
1499
|
|
|
|
1500
|
|
|
// if, for some reason, file could not be created |
1501
|
|
|
} elseif (@!imagejpeg($identifier, $this->target_path, $this->jpeg_quality)) { |
1502
|
|
|
|
1503
|
|
|
// save the error level and stop the execution of the script |
1504
|
|
|
$this->error = 3; |
1505
|
|
|
|
1506
|
|
|
return false; |
1507
|
|
|
} |
1508
|
|
|
|
1509
|
|
|
break; |
1510
|
|
|
|
1511
|
|
|
// if PNG |
1512
|
|
View Code Duplication |
case 'png': |
|
|
|
|
1513
|
|
|
|
1514
|
|
|
// save full alpha channel information |
1515
|
|
|
imagesavealpha($identifier, true); |
1516
|
|
|
|
1517
|
|
|
// if GD support for this file type is not available |
1518
|
|
|
if (!function_exists('imagepng')) { |
1519
|
|
|
|
1520
|
|
|
// save the error level and stop the execution of the script |
1521
|
|
|
$this->error = 6; |
1522
|
|
|
|
1523
|
|
|
return false; |
1524
|
|
|
|
1525
|
|
|
// if, for some reason, file could not be created |
1526
|
|
|
} elseif (@!imagepng($identifier, $this->target_path, $this->png_compression)) { |
1527
|
|
|
|
1528
|
|
|
// save the error level and stop the execution of the script |
1529
|
|
|
$this->error = 3; |
1530
|
|
|
|
1531
|
|
|
return false; |
1532
|
|
|
} |
1533
|
|
|
|
1534
|
|
|
break; |
1535
|
|
|
|
1536
|
|
|
// if not a supported file extension |
1537
|
|
|
default: |
|
|
|
|
1538
|
|
|
|
1539
|
|
|
// save the error level and stop the execution of the script |
1540
|
|
|
$this->error = 5; |
1541
|
|
|
|
1542
|
|
|
return false; |
1543
|
|
|
|
1544
|
|
|
} |
1545
|
|
|
|
1546
|
|
|
// get a list of functions disabled via configuration |
1547
|
|
|
$disabled_functions = @ini_get('disable_functions'); |
1548
|
|
|
|
1549
|
|
|
// if the 'chmod' function is not disabled via configuration |
1550
|
|
|
if ($disabled_functions == '' || strpos('chmod', $disabled_functions) === false) { |
1551
|
|
|
|
1552
|
|
|
// chmod the file |
1553
|
|
|
chmod($this->target_path, (int)$this->chmod_value, 8); |
1554
|
|
|
|
1555
|
|
|
// save the error level |
1556
|
|
|
} else { |
1557
|
|
|
$this->error = 8; |
1558
|
|
|
} |
1559
|
|
|
|
1560
|
|
|
// if target file has to have the same timestamp as the source image |
1561
|
|
|
if ($this->preserve_time && isset($this->source_image_time)) { |
1562
|
|
|
|
1563
|
|
|
// touch the newly created file |
1564
|
|
|
@touch($this->target_path, $this->source_image_time); |
|
|
|
|
1565
|
|
|
} |
1566
|
|
|
|
1567
|
|
|
// return true |
1568
|
|
|
return true; |
1569
|
|
|
} |
1570
|
|
|
} |
1571
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.