Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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