source: branches/opera/plugins/ImageManager/Classes/GD.php @ 428

Last change on this file since 428 was 428, checked in by gogo, 14 years ago

This branch contains preliminary work for supporting Opera.

Opera technology preview which includes Rich Editing (designMode
style) may be downloaded at http://snapshot.opera.com/

Currently with only a few modifications (and identifing as Gecko for the
time being) Xinha actually works to a useful degree.

File size: 16.9 KB
Line 
1<?php
2/***********************************************************************
3** Title.........:  GD Driver
4** Version.......:  1.0
5** Author........:  Xiang Wei ZHUO <wei@zhuo.org>
6** Filename......:  GD.php
7** Last changed..:  30 Aug 2003
8** Notes.........:  Orginal is from PEAR
9**/
10// +----------------------------------------------------------------------+
11// | PHP Version 4                                                        |
12// +----------------------------------------------------------------------+
13// | Copyright (c) 1997-2002 The PHP Group                                |
14// +----------------------------------------------------------------------+
15// | This source file is subject to version 2.02 of the PHP license,      |
16// | that is bundled with this package in the file LICENSE, and is        |
17// | available at through the world-wide-web at                           |
18// | http://www.php.net/license/2_02.txt.                                 |
19// | If you did not receive a copy of the PHP license and are unable to   |
20// | obtain it through the world-wide-web, please send a note to          |
21// | license@php.net so we can mail you a copy immediately.               |
22// +----------------------------------------------------------------------+
23// | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
24// |          Alan Knowles <alan@akbkhome.com>                            |
25// +----------------------------------------------------------------------+
26//
27//    Usage :
28//    $img    = new Image_Transform_GD();
29//    $angle  = -78;
30//    $img->load('magick.png');
31//
32//    if($img->rotate($angle,array('autoresize'=>true,'color_mask'=>array(255,0,0)))){
33//        $img->addText(array('text'=>"Rotation $angle",'x'=>0,'y'=>100,'font'=>'/usr/share/fonts/default/TrueType/cogb____.ttf'));
34//        $img->display();
35//    } else {
36//        echo "Error";
37//    }
38//
39//
40// $Id: GD.php 26 2004-03-31 02:35:21Z Wei Zhuo $
41//
42// Image Transformation interface using the GD library
43//
44
45require_once "Transform.php";
46
47Class Image_Transform_Driver_GD extends Image_Transform
48{
49    /**
50     * Holds the image file for manipulation
51     */
52    var $imageHandle = '';
53
54    /**
55     * Holds the original image file
56     */
57    var $old_image = '';
58
59    /**
60     * Check settings
61     *
62     * @return mixed true or  or a PEAR error object on error
63     *
64     * @see PEAR::isError()
65     */
66    function Image_Transform_GD()
67    {
68        return;
69    } // End function Image
70
71    /**
72     * Load image
73     *
74     * @param string filename
75     *
76     * @return mixed none or a PEAR error object on error
77     * @see PEAR::isError()
78     */
79    function load($image)
80    {
81        $this->uid = md5($_SERVER['REMOTE_ADDR']);
82        $this->image = $image;
83        $this->_get_image_details($image);
84        $functionName = 'ImageCreateFrom' . $this->type;
85                if(function_exists($functionName))
86                {
87                        $this->imageHandle = $functionName($this->image);
88                }
89    } // End load
90
91    /**
92     * addText
93     *
94     * @param   array   options     Array contains options
95     *                              array(
96     *                                  'text'  The string to draw
97     *                                  'x'     Horizontal position
98     *                                  'y'     Vertical Position
99     *                                  'Color' Font color
100     *                                  'font'  Font to be used
101     *                                  'size'  Size of the fonts in pixel
102     *                                  'resize_first'  Tell if the image has to be resized
103     *                                                  before drawing the text
104     *                              )
105     *
106     * @return none
107     * @see PEAR::isError()
108     */
109    function addText($params)
110    {
111        $default_params = array(
112                                'text' => 'This is Text',
113                                'x' => 10,
114                                'y' => 20,
115                                'color' => array(255,0,0),
116                                'font' => 'Arial.ttf',
117                                'size' => '12',
118                                'angle' => 0,
119                                'resize_first' => false // Carry out the scaling of the image before annotation?  Not used for GD
120                                );
121        $params = array_merge($default_params, $params);
122        extract($params);
123
124        if( !is_array($color) ){
125            if ($color[0]=='#'){
126                $this->colorhex2colorarray( $color );
127            } else {
128                include_once('Image/Transform/Driver/ColorsDefs.php');
129                $color = isset($colornames[$color])?$colornames[$color]:false;
130            }
131        }
132
133        $c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);
134
135        if ('ttf' == substr($font, -3)) {
136            ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
137        } else {
138            ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
139        }
140        return true;
141    } // End addText
142
143
144    /**
145     * Rotate image by the given angle
146     * Uses a fast rotation algorythm for custom angles
147     * or lines copy for multiple of 90 degrees
148     *
149     * @param int       $angle      Rotation angle
150     * @param array     $options    array(  'autoresize'=>true|false,
151     *                                      'color_mask'=>array(r,g,b), named color or #rrggbb
152     *                                   )
153     * @author Pierre-Alain Joye
154     * @return mixed none or a PEAR error object on error
155     * @see PEAR::isError()
156     */
157    function rotate($angle, $options=null)
158    {
159        if(function_exists('imagerotate')) {
160            $white = imagecolorallocate ($this->imageHandle, 255, 255, 255);
161                        $this->imageHandle = imagerotate($this->imageHandle, $angle, $white);
162            return true;
163        }
164
165        if ( $options==null ){
166            $autoresize = true;
167            $color_mask = array(255,255,0);
168        } else {
169            extract( $options );
170        }
171
172        while ($angle <= -45) {
173            $angle  += 360;
174        }
175        while ($angle > 270) {
176            $angle  -= 360;
177        }
178
179        $t      = deg2rad($angle);
180
181        if( !is_array($color_mask) ){
182            if ($color[0]=='#'){
183                $this->colorhex2colorarray( $color_mask );
184            } else {
185                include_once('Image/Transform/Driver/ColorDefs.php');
186                $color = isset($colornames[$color_mask])?$colornames[$color_mask]:false;
187            }
188        }
189
190        // Do not round it, too much lost of quality
191        $cosT   = cos($t);
192        $sinT   = sin($t);
193
194        $img    =& $this->imageHandle;
195
196        $width  = $max_x  = $this->img_x;
197        $height = $max_y  = $this->img_y;
198        $min_y  = 0;
199        $min_x  = 0;
200
201        $x1     = round($max_x/2,0);
202        $y1     = round($max_y/2,0);
203
204        if ( $autoresize ){
205            $t      = abs($t);
206            $a      = round($angle,0);
207            switch((int)($angle)){
208                case 0:
209                        $width2     = $width;
210                        $height2    = $height;
211                    break;
212                case 90:
213                        $width2     = $height;
214                        $height2    = $width;
215                    break;
216                case 180:
217                        $width2     = $width;
218                        $height2    = $height;
219                    break;
220                case 270:
221                        $width2     = $height;
222                        $height2    = $width;
223                    break;
224                default:
225                    $width2     = (int)(abs(sin($t) * $height + cos($t) * $width));
226                    $height2    = (int)(abs(cos($t) * $height+sin($t) * $width));
227            }
228
229            $width2     -= $width2%2;
230            $height2    -= $height2%2;
231
232            $d_width    = abs($width - $width2);
233            $d_height   = abs($height - $height2);
234            $x_offset   = $d_width/2;
235            $y_offset   = $d_height/2;
236            $min_x2     = -abs($x_offset);
237            $min_y2     = -abs($y_offset);
238            $max_x2     = $width2;
239            $max_y2     = $height2;
240        }
241
242        $img2   = @imagecreate($width2,$height2);
243
244        if ( !is_resource($img2) ){
245            return false;/*PEAR::raiseError('Cannot create buffer for the rotataion.',
246                                null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
247        }
248
249        $this->img_x = $width2;
250        $this->img_y = $height2;
251
252
253        imagepalettecopy($img2,$img);
254
255        $mask   = imagecolorresolve($img2,$color_mask[0],$color_mask[1],$color_mask[2]);
256
257        // use simple lines copy for axes angles
258        switch((int)($angle)){
259            case 0:
260                imagefill ($img2, 0, 0,$mask);
261                for ($y=0; $y < $max_y; $y++) {
262                    for ($x = $min_x; $x < $max_x; $x++){
263                        $c  = @imagecolorat ( $img, $x, $y);
264                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
265                    }
266                }
267                break;
268            case 90:
269                imagefill ($img2, 0, 0,$mask);
270                for ($x = $min_x; $x < $max_x; $x++){
271                    for ($y=$min_y; $y < $max_y; $y++) {
272                        $c  = imagecolorat ( $img, $x, $y);
273                        imagesetpixel($img2,$max_y-$y-1,$x,$c);
274                    }
275                }
276                break;
277            case 180:
278                imagefill ($img2, 0, 0,$mask);
279                for ($y=0; $y < $max_y; $y++) {
280                    for ($x = $min_x; $x < $max_x; $x++){
281                        $c  = @imagecolorat ( $img, $x, $y);
282                        imagesetpixel($img2, $max_x2-$x-1, $max_y2-$y-1, $c);
283                    }
284                }
285                break;
286            case 270:
287                imagefill ($img2, 0, 0,$mask);
288                for ($y=0; $y < $max_y; $y++) {
289                    for ($x = $max_x; $x >= $min_x; $x--){
290                        $c  = @imagecolorat ( $img, $x, $y);
291                        imagesetpixel($img2,$y,$max_x-$x-1,$c);
292                    }
293                }
294                break;
295            // simple reverse rotation algo
296            default:
297                $i=0;
298                for ($y = $min_y2; $y < $max_y2; $y++){
299
300                    // Algebra :)
301                    $x2 = round((($min_x2-$x1) * $cosT) + (($y-$y1) * $sinT + $x1),0);
302                    $y2 = round((($y-$y1) * $cosT - ($min_x2-$x1) * $sinT + $y1),0);
303
304                    for ($x = $min_x2; $x < $max_x2; $x++){
305
306                        // Check if we are out of original bounces, if we are
307                        // use the default color mask
308                        if ( $x2>=0 && $x2<$max_x && $y2>=0 && $y2<$max_y ){
309                            $c  = imagecolorat ( $img, $x2, $y2);
310                        } else {
311                            $c  = $mask;
312                        }
313                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
314
315                        // round verboten!
316                        $x2  += $cosT;
317                        $y2  -= $sinT;
318                    }
319                }
320                break;
321        }
322        $this->old_image    = $this->imageHandle;
323        $this->imageHandle  =  $img2;
324        return true;
325    }
326
327
328   /**
329    * Resize Action
330    *
331    * For GD 2.01+ the new copyresampled function is used
332    * It uses a bicubic interpolation algorithm to get far
333    * better result.
334    *
335    * @param int  $new_x new width
336    * @param int  $new_y new height
337    *
338    * @return true on success or pear error
339    * @see PEAR::isError()
340    */
341    function _resize($new_x, $new_y) {
342        if ($this->resized === true) {
343            return false; /*PEAR::raiseError('You have already resized the image without saving it.  Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
344        }
345        if(function_exists('ImageCreateTrueColor')){
346            $new_img =ImageCreateTrueColor($new_x,$new_y);
347        } else {
348            $new_img =ImageCreate($new_x,$new_y);
349        }
350        if(function_exists('ImageCopyResampled')){
351            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
352        } else {
353            ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
354        }
355        $this->old_image = $this->imageHandle;
356        $this->imageHandle = $new_img;
357        $this->resized = true;
358
359        $this->new_x = $new_x;
360        $this->new_y = $new_y;
361        return true;
362    }
363
364    /**
365     * Crop the image
366     *
367     * @param int $crop_x left column of the image
368     * @param int $crop_y top row of the image
369     * @param int $crop_width new cropped image width
370     * @param int $crop_height new cropped image height
371     */
372    function crop($new_x, $new_y, $new_width, $new_height)
373    {
374        if(function_exists('ImageCreateTrueColor')){
375            $new_img =ImageCreateTrueColor($new_width,$new_height);
376        } else {
377            $new_img =ImageCreate($new_width,$new_height);
378        }
379        if(function_exists('ImageCopyResampled')){
380            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, $new_x, $new_y,$new_width,$new_height,$new_width,$new_height);
381        } else {
382            ImageCopyResized($new_img, $this->imageHandle, 0, 0, $new_x, $new_y, $new_width,$new_height,$new_width,$new_height);
383        }
384        $this->old_image = $this->imageHandle;
385        $this->imageHandle = $new_img;
386        $this->resized = true;
387
388        $this->new_x = $new_x;
389        $this->new_y = $new_y;
390        return true;
391    }
392   
393    /**
394     * Flip the image horizontally or vertically
395     *
396     * @param boolean $horizontal true if horizontal flip, vertical otherwise
397     */
398    function flip($horizontal)
399    {
400        if(!$horizontal) {
401            $this->rotate(180);
402        }
403
404        $width = imagesx($this->imageHandle);
405        $height = imagesy($this->imageHandle);
406
407        for ($j = 0; $j < $height; $j++) {
408                $left = 0;
409                $right = $width-1;
410
411
412                while ($left < $right) {
413                    //echo " j:".$j." l:".$left." r:".$right."\n<br>";
414                    $t = imagecolorat($this->imageHandle, $left, $j);
415                    imagesetpixel($this->imageHandle, $left, $j, imagecolorat($this->imageHandle, $right, $j));
416                    imagesetpixel($this->imageHandle, $right, $j, $t);
417                    $left++; $right--;
418                }
419           
420        }
421
422        return true;
423    }
424
425
426    /**
427     * Adjust the image gamma
428     *
429     * @param float $outputgamma
430     *
431     * @return none
432     */
433    function gamma($outputgamma=1.0) {
434        ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);
435    }
436
437    /**
438     * Save the image file
439     *
440     * @param string  $filename the name of the file to write to
441     * @param int     $quality  output DPI, default is 85
442     * @param string  $types    define the output format, default
443     *                          is the current used format
444     *
445     * @return none
446     */
447    function save($filename, $type = '', $quality = 85)
448    {
449                $type           = $type==''? $this->type : $type;
450                $functionName   = 'image' . $type;
451
452                if(function_exists($functionName))
453                {
454                        $this->old_image = $this->imageHandle;
455                        if($type=='jpeg')
456                                $functionName($this->imageHandle, $filename, $quality);
457                        else
458                                $functionName($this->imageHandle, $filename);
459                        $this->imageHandle = $this->old_image;
460                        $this->resized = false;
461                }
462    } // End save
463
464
465    /**
466     * Display image without saving and lose changes
467     *
468     * @param string type (JPG,PNG...);
469     * @param int quality 75
470     *
471     * @return none
472     */
473    function display($type = '', $quality = 75)
474    {
475        if ($type != '') {
476            $this->type = $type;
477        }
478        $functionName = 'Image' . $this->type;
479                if(function_exists($functionName))
480                {
481                        header('Content-type: image/' . strtolower($this->type));
482                        $functionName($this->imageHandle, '', $quality);
483                        $this->imageHandle = $this->old_image;
484                        $this->resized = false;
485                        ImageDestroy($this->old_image);
486                        $this->free();
487                }
488    }
489
490    /**
491     * Destroy image handle
492     *
493     * @return none
494     */
495    function free()
496    {
497        if ($this->imageHandle){
498            ImageDestroy($this->imageHandle);
499        }
500    }
501
502} // End class ImageGD
503?>
Note: See TracBrowser for help on using the repository browser.