1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
/* vim: set expandtab tabstop=4 shiftwidth=4: */ |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* ImageMagick binaries implementation for Image_Transform package |
7
|
|
|
* |
8
|
|
|
* PHP versions 4 and 5 |
9
|
|
|
* |
10
|
|
|
* LICENSE: This source file is subject to version 3.0 of the PHP license |
11
|
|
|
* that is available through the world-wide-web at the following URI: |
12
|
|
|
* http://www.php.net/license/3_0.txt. If you did not receive a copy of |
13
|
|
|
* the PHP License and are unable to obtain it through the web, please |
14
|
|
|
* send a note to [email protected] so we can mail you a copy immediately. |
15
|
|
|
* |
16
|
|
|
* @category Image |
17
|
|
|
* @package Image_Transform |
18
|
|
|
* @author Peter Bowyer <[email protected]> |
19
|
|
|
* @author Philippe Jausions <[email protected]> |
20
|
|
|
* @copyright 2002-2005 The PHP Group |
21
|
|
|
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
22
|
|
|
* @version CVS: $Id: IM.php 266859 2008-09-30 22:28:47Z dufuz $ |
23
|
|
|
* @link http://pear.php.net/package/Image_Transform |
24
|
|
|
*/ |
25
|
|
|
|
26
|
|
|
//require_once 'Image/Transform.php'; |
|
|
|
|
27
|
|
|
//require_once 'System.php'; |
28
|
|
|
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/Image/Transform.php'; |
29
|
|
|
require_once XOOPS_ROOT_PATH . '/modules/extgallery/class/pear/System.php'; |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* ImageMagick binaries implementation for Image_Transform package |
33
|
|
|
* |
34
|
|
|
* @category Image |
35
|
|
|
* @package Image_Transform |
36
|
|
|
* @subpackage Image_Transform_Driver_IM |
37
|
|
|
* @author Peter Bowyer <[email protected]> |
38
|
|
|
* @author Philippe Jausions <[email protected]> |
39
|
|
|
* @copyright 2002-2005 The PHP Group |
40
|
|
|
* @license http://www.php.net/license/3_0.txt PHP License 3.0 |
41
|
|
|
* @version Release: @package_version@ |
42
|
|
|
* @link http://pear.php.net/package/Image_Transform |
43
|
|
|
* @link http://www.imagemagick.org/ |
44
|
|
|
**/ |
45
|
|
|
class Image_Transform_Driver_IM extends Image_Transform |
|
|
|
|
46
|
|
|
{ |
47
|
|
|
/** |
48
|
|
|
* associative array commands to be executed |
49
|
|
|
* @var array |
50
|
|
|
* @access private |
51
|
|
|
*/ |
52
|
|
|
var $command; |
|
|
|
|
53
|
|
|
|
54
|
|
|
/** |
55
|
|
|
* Class constructor |
56
|
|
|
*/ |
57
|
|
|
function Image_Transform_Driver_IM() |
|
|
|
|
58
|
|
|
{ |
59
|
|
|
$this->__construct(); |
60
|
|
|
} // End Image_IM |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* Class constructor |
64
|
|
|
*/ |
65
|
|
View Code Duplication |
function __construct() |
|
|
|
|
66
|
|
|
{ |
67
|
|
|
$this->_init(); |
68
|
|
|
if (!defined('IMAGE_TRANSFORM_IM_PATH')) { |
69
|
|
|
$path = dirname(System::which('convert')) |
70
|
|
|
. DIRECTORY_SEPARATOR; |
71
|
|
|
define('IMAGE_TRANSFORM_IM_PATH', $path); |
72
|
|
|
} |
73
|
|
|
if (System::which(IMAGE_TRANSFORM_IM_PATH . 'convert' . ((OS_WINDOWS) ? '.exe' : ''))) { |
74
|
|
|
include 'Image/Transform/Driver/Imagick/ImageTypes.php'; |
75
|
|
|
} else { |
76
|
|
|
$this->isError(PEAR::raiseError('Couldn\'t find "convert" binary', |
|
|
|
|
77
|
|
|
IMAGE_TRANSFORM_ERROR_UNSUPPORTED)); |
78
|
|
|
} |
79
|
|
|
} // End Image_IM |
80
|
|
|
|
81
|
|
|
/** |
82
|
|
|
* Initialize the state of the object |
83
|
|
|
**/ |
84
|
|
|
function _init() |
|
|
|
|
85
|
|
|
{ |
86
|
|
|
$this->command = array(); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Load an image. |
91
|
|
|
* |
92
|
|
|
* This method doesn't support remote files. |
93
|
|
|
* |
94
|
|
|
* @param string filename |
95
|
|
|
* |
96
|
|
|
* @return mixed TRUE or a PEAR error object on error |
97
|
|
|
* @see PEAR::isError() |
98
|
|
|
*/ |
99
|
|
|
function load($image) |
|
|
|
|
100
|
|
|
{ |
101
|
|
|
$this->_init(); |
102
|
|
|
if (!file_exists($image)) { |
103
|
|
|
return PEAR::raiseError('The image file ' . $image |
|
|
|
|
104
|
|
|
. ' doesn\'t exist', IMAGE_TRANSFORM_ERROR_IO); |
105
|
|
|
} |
106
|
|
|
$this->image = $image; |
107
|
|
|
$result = $this->_get_image_details($image); |
108
|
|
|
if (PEAR::isError($result)) { |
109
|
|
|
return $result; |
|
|
|
|
110
|
|
|
} |
111
|
|
|
return true; |
|
|
|
|
112
|
|
|
|
113
|
|
|
} // End load |
114
|
|
|
|
115
|
|
|
/** |
116
|
|
|
* Image_Transform_Driver_IM::_get_image_details() |
117
|
|
|
* |
118
|
|
|
* @param string $image the path and name of the image file |
119
|
|
|
* @return none |
120
|
|
|
*/ |
121
|
|
|
function _get_image_details($image) |
|
|
|
|
122
|
|
|
{ |
123
|
|
|
$retval = Image_Transform::_get_image_details($image); |
124
|
|
|
if (PEAR::isError($retval)) { |
125
|
|
|
unset($retval); |
126
|
|
|
|
127
|
|
|
if (!System::which(IMAGE_TRANSFORM_IM_PATH . 'identify' . ((OS_WINDOWS) ? '.exe' : ''))) { |
128
|
|
|
$this->isError(PEAR::raiseError('Couldn\'t find "identify" binary', IMAGE_TRANSFORM_ERROR_UNSUPPORTED)); |
|
|
|
|
129
|
|
|
} |
130
|
|
|
$cmd = $this->_prepare_cmd(IMAGE_TRANSFORM_IM_PATH, |
131
|
|
|
'identify', |
132
|
|
|
'-format %w:%h:%m ' . escapeshellarg($image)); |
133
|
|
|
exec($cmd, $res, $exit); |
134
|
|
|
|
135
|
|
|
if ($exit != 0) { |
|
|
|
|
136
|
|
|
return PEAR::raiseError("Cannot fetch image or images details.", true); |
|
|
|
|
137
|
|
|
} |
138
|
|
|
|
139
|
|
|
$data = explode(':', $res[0]); |
140
|
|
|
$this->img_x = $data[0]; |
141
|
|
|
$this->img_y = $data[1]; |
142
|
|
|
$this->type = strtolower($data[2]); |
143
|
|
|
$retval = true; |
144
|
|
|
|
145
|
|
|
} |
146
|
|
|
|
147
|
|
|
return $retval; |
148
|
|
|
} |
149
|
|
|
|
150
|
|
|
/** |
151
|
|
|
* Resize the image. |
152
|
|
|
* |
153
|
|
|
* @access private |
154
|
|
|
* |
155
|
|
|
* @param int $new_x New width |
156
|
|
|
* @param int $new_y New height |
157
|
|
|
* @param mixed $options Optional parameters |
158
|
|
|
* |
159
|
|
|
* @return true on success or PEAR Error object on error |
160
|
|
|
* @see PEAR::isError() |
161
|
|
|
*/ |
162
|
|
|
function _resize($new_x, $new_y, $options = null) |
|
|
|
|
163
|
|
|
{ |
164
|
|
|
if (isset($this->command['resize'])) { |
165
|
|
|
return PEAR::raiseError('You cannot scale or resize an image more than once without calling save() or display()', true); |
|
|
|
|
166
|
|
|
} |
167
|
|
|
$this->command['resize'] = '-geometry ' |
168
|
|
|
. ((int) $new_x) . 'x' . ((int) $new_y) . '!'; |
169
|
|
|
|
170
|
|
|
$this->new_x = $new_x; |
171
|
|
|
$this->new_y = $new_y; |
172
|
|
|
|
173
|
|
|
return true; |
|
|
|
|
174
|
|
|
} // End resize |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* rotate |
178
|
|
|
* |
179
|
|
|
* @param int angle rotation angle |
180
|
|
|
* @param array options no option allowed |
181
|
|
|
* @return mixed TRUE or a PEAR error object on error |
182
|
|
|
*/ |
183
|
|
|
function rotate($angle, $options = null) |
|
|
|
|
184
|
|
|
{ |
185
|
|
|
$angle = $this->_rotation_angle($angle); |
186
|
|
|
if ($angle % 360) { |
187
|
|
|
$this->command['rotate'] = '-rotate ' . (float) $angle; |
188
|
|
|
} |
189
|
|
|
return true; |
190
|
|
|
|
191
|
|
|
} // End rotate |
192
|
|
|
|
193
|
|
|
/** |
194
|
|
|
* Crop image |
195
|
|
|
* |
196
|
|
|
* @author Ian Eure <[email protected]> |
197
|
|
|
* @since 0.8 |
198
|
|
|
* |
199
|
|
|
* @param int width Cropped image width |
200
|
|
|
* @param int height Cropped image height |
201
|
|
|
* @param int x X-coordinate to crop at |
202
|
|
|
* @param int y Y-coordinate to crop at |
203
|
|
|
* |
204
|
|
|
* @return mixed TRUE or a PEAR error object on error |
205
|
|
|
*/ |
206
|
|
|
function crop($width, $height, $x = 0, $y = 0) { |
|
|
|
|
207
|
|
|
// Do we want a safety check - i.e. if $width+$x > $this->img_x then we |
208
|
|
|
// raise a warning? [and obviously same for $height+$y] |
209
|
|
|
$this->command['crop'] = '-crop ' |
210
|
|
|
. ((int) $width) . 'x' . ((int) $height) |
211
|
|
|
. '+' . ((int) $x) . '+' . ((int) $y) . '!'; |
212
|
|
|
|
213
|
|
|
// I think that setting img_x/y is wrong, but scaleByLength() & friends |
214
|
|
|
// mess up the aspect after a crop otherwise. |
215
|
|
|
$this->new_x = $this->img_x = $width - $x; |
|
|
|
|
216
|
|
|
$this->new_y = $this->img_y = $height - $y; |
|
|
|
|
217
|
|
|
|
218
|
|
|
return true; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
/** |
222
|
|
|
* addText |
223
|
|
|
* |
224
|
|
|
* @param array options Array contains options |
225
|
|
|
* array( |
226
|
|
|
* 'text' The string to draw |
227
|
|
|
* 'x' Horizontal position |
228
|
|
|
* 'y' Vertical Position |
229
|
|
|
* 'Color' Font color |
230
|
|
|
* 'font' Font to be used |
231
|
|
|
* 'size' Size of the fonts in pixel |
232
|
|
|
* 'resize_first' Tell if the image has to be resized |
233
|
|
|
* before drawing the text |
234
|
|
|
* ) |
235
|
|
|
* |
236
|
|
|
* @return mixed TRUE or a PEAR error object on error |
237
|
|
|
* @see PEAR::isError() |
238
|
|
|
*/ |
239
|
|
|
function addText($params) |
|
|
|
|
240
|
|
|
{ |
241
|
|
|
$this->old_image = $this->imageHandle; |
|
|
|
|
242
|
|
|
$params = array_merge($this->_get_default_text_params(), $params); |
243
|
|
|
extract($params); |
244
|
|
|
|
245
|
|
|
if (true === $resize_first) { |
246
|
|
|
// Set the key so that this will be the last item in the array |
247
|
|
|
$key = 'ztext'; |
248
|
|
|
} else { |
249
|
|
|
$key = 'text'; |
250
|
|
|
} |
251
|
|
|
$this->command[$key] = '-font ' . escapeshellarg($font) |
252
|
|
|
. ' -fill ' . escapeshellarg($color) |
253
|
|
|
. ' -draw \'text ' . escapeshellarg($x . ',' . $y) |
254
|
|
|
. ' "' . escapeshellarg($text) . '"\''; |
255
|
|
|
// Producing error: gs: not found gs: not found convert: Postscript delegate failed [No such file or directory]. |
256
|
|
|
return true; |
257
|
|
|
|
258
|
|
|
} // End addText |
259
|
|
|
|
260
|
|
|
/** |
261
|
|
|
* Adjust the image gamma |
262
|
|
|
* |
263
|
|
|
* @access public |
264
|
|
|
* @param float $outputgamma |
265
|
|
|
* @return mixed TRUE or a PEAR error object on error |
266
|
|
|
*/ |
267
|
|
|
function gamma($outputgamma = 1.0) { |
|
|
|
|
268
|
|
|
if ($outputgamme != 1.0) { |
|
|
|
|
269
|
|
|
$this->command['gamma'] = '-gamma ' . (float) $outputgamma; |
270
|
|
|
} |
271
|
|
|
return true; |
272
|
|
|
} |
273
|
|
|
|
274
|
|
|
/** |
275
|
|
|
* Convert the image to greyscale |
276
|
|
|
* |
277
|
|
|
* @access public |
278
|
|
|
* @return mixed TRUE or a PEAR error object on error |
279
|
|
|
*/ |
280
|
|
|
function greyscale() { |
|
|
|
|
281
|
|
|
$this->command['type'] = '-type Grayscale'; |
282
|
|
|
return true; |
283
|
|
|
} |
284
|
|
|
|
285
|
|
|
/** |
286
|
|
|
* Horizontal mirroring |
287
|
|
|
* |
288
|
|
|
* @access public |
289
|
|
|
* @return TRUE or PEAR Error object on error |
|
|
|
|
290
|
|
|
*/ |
291
|
|
View Code Duplication |
function mirror() { |
|
|
|
|
292
|
|
|
// We can only apply "flop" once |
293
|
|
|
if (isset($this->command['flop'])) { |
294
|
|
|
unset($this->command['flop']); |
295
|
|
|
} else { |
296
|
|
|
$this->command['flop'] = '-flop'; |
297
|
|
|
} |
298
|
|
|
return true; |
299
|
|
|
} |
300
|
|
|
|
301
|
|
|
/** |
302
|
|
|
* Vertical mirroring |
303
|
|
|
* |
304
|
|
|
* @access public |
305
|
|
|
* @return TRUE or PEAR Error object on error |
|
|
|
|
306
|
|
|
*/ |
307
|
|
View Code Duplication |
function flip() { |
|
|
|
|
308
|
|
|
// We can only apply "flip" once |
309
|
|
|
if (isset($this->command['flip'])) { |
310
|
|
|
unset($this->command['flip']); |
311
|
|
|
} else { |
312
|
|
|
$this->command['flip'] = '-flip'; |
313
|
|
|
} |
314
|
|
|
return true; |
|
|
|
|
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
/** |
318
|
|
|
* Save the image file |
319
|
|
|
* |
320
|
|
|
* @access public |
321
|
|
|
* |
322
|
|
|
* @param $filename string the name of the file to write to |
323
|
|
|
* @param $quality quality image dpi, default=75 |
324
|
|
|
* @param $type string (JPEG, PNG...) |
325
|
|
|
* |
326
|
|
|
* @return mixed TRUE or a PEAR error object on error |
327
|
|
|
*/ |
328
|
|
|
function save($filename, $type = '', $quality = null) |
|
|
|
|
329
|
|
|
{ |
330
|
|
|
$type = strtoupper(($type == '') ? $this->type : $type); |
331
|
|
|
switch ($type) { |
332
|
|
|
case 'JPEG': |
333
|
|
|
$type = 'JPG'; |
334
|
|
|
break; |
335
|
|
|
} |
336
|
|
|
$options = array(); |
337
|
|
|
if (!is_null($quality)) { |
338
|
|
|
$options['quality'] = $quality; |
339
|
|
|
} |
340
|
|
|
$quality = $this->_getOption('quality', $options, 75); |
341
|
|
|
|
342
|
|
|
$cmd = $this->_prepare_cmd( |
343
|
|
|
IMAGE_TRANSFORM_IM_PATH, |
344
|
|
|
'convert', |
345
|
|
|
implode(' ', $this->command) |
346
|
|
|
. ' -quality ' . ((int) $quality) . ' ' |
347
|
|
|
. escapeshellarg($this->image) . ' ' . $type . ':' |
348
|
|
|
. escapeshellarg($filename) . ' 2>&1'); |
349
|
|
|
exec($cmd, $res, $exit); |
350
|
|
|
|
351
|
|
|
if (!$this->keep_settings_on_save) { |
352
|
|
|
$this->free(); |
353
|
|
|
} |
354
|
|
|
|
355
|
|
|
return ($exit == 0) ? true : PEAR::raiseError(implode('. ', $res), |
|
|
|
|
356
|
|
|
IMAGE_TRANSFORM_ERROR_IO); |
357
|
|
|
} // End save |
358
|
|
|
|
359
|
|
|
/** |
360
|
|
|
* Display image without saving and lose changes |
361
|
|
|
* |
362
|
|
|
* This method adds the Content-type HTTP header |
363
|
|
|
* |
364
|
|
|
* @access public |
365
|
|
|
* |
366
|
|
|
* @param string type (JPEG,PNG...); |
367
|
|
|
* @param int quality 75 |
368
|
|
|
* |
369
|
|
|
* @return mixed TRUE or a PEAR error object on error |
370
|
|
|
*/ |
371
|
|
|
function display($type = '', $quality = null) |
|
|
|
|
372
|
|
|
{ |
373
|
|
|
$type = strtoupper(($type == '') ? $this->type : $type); |
374
|
|
|
switch ($type) { |
375
|
|
|
case 'JPEG': |
376
|
|
|
$type = 'JPG'; |
377
|
|
|
break; |
378
|
|
|
} |
379
|
|
|
$options = array(); |
380
|
|
|
if (!is_null($quality)) { |
381
|
|
|
$options['quality'] = $quality; |
382
|
|
|
} |
383
|
|
|
$quality = $this->_getOption('quality', $options, 75); |
384
|
|
|
|
385
|
|
|
$this->_send_display_headers($type); |
386
|
|
|
|
387
|
|
|
$cmd = $this->_prepare_cmd( |
388
|
|
|
IMAGE_TRANSFORM_IM_PATH, |
389
|
|
|
'convert', |
390
|
|
|
implode(' ', $this->command) . " -quality $quality " . |
391
|
|
|
$this->image . ' ' . $type . ":-"); |
392
|
|
|
passthru($cmd); |
393
|
|
|
|
394
|
|
|
if (!$this->keep_settings_on_save) { |
395
|
|
|
$this->free(); |
396
|
|
|
} |
397
|
|
|
return true; |
|
|
|
|
398
|
|
|
} |
399
|
|
|
|
400
|
|
|
/** |
401
|
|
|
* Destroy image handle |
402
|
|
|
* |
403
|
|
|
* @return void |
404
|
|
|
*/ |
405
|
|
|
function free() |
|
|
|
|
406
|
|
|
{ |
407
|
|
|
$this->command = array(); |
408
|
|
|
$this->image = ''; |
409
|
|
|
$this->type = ''; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
} // End class ImageIM |
413
|
|
|
|
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.