upload
[pear] / Image / Transform / Driver / GD1.php
1 <?php
2 // +----------------------------------------------------------------------+
3 // | PHP Version 4                                                        |
4 // +----------------------------------------------------------------------+
5 // | Copyright (c) 1997-2003 The PHP Group                                |
6 // +----------------------------------------------------------------------+
7 // | This source file is subject to version 2.02 of the PHP license,      |
8 // | that is bundled with this package in the file LICENSE, and is        |
9 // | available at through the world-wide-web at                           |
10 // | http://www.php.net/license/2_02.txt.                                 |
11 // | If you did not receive a copy of the PHP license and are unable to   |
12 // | obtain it through the world-wide-web, please send a note to          |
13 // | license@php.net so we can mail you a copy immediately.               |
14 // +----------------------------------------------------------------------+
15 // | Authors: Peter Bowyer <peter@mapledesign.co.uk>                      |
16 // |          Alan Knowles <alan@akbkhome.com>                            |
17 // +----------------------------------------------------------------------+
18
19 require_once 'Image/Transform/Driver/GD.php';
20
21 /**
22  * This driver is for GD1 or the non-bundled version of GD2
23  *
24  * @package
25  * @author NAWAL ASWAN
26  * @copyright Copyright (c) 2003
27  * @version $Id: GD1.php 287351 2009-08-16 03:28:48Z clockwerx $
28  * @access public
29  **/
30 Class Image_Transform_Driver_GD1 extends Image_Transform_Driver_GD
31 {
32     /**
33      * Check settings
34      *
35      * @return mixed true or  or a PEAR error object on error
36      *
37      * @see PEAR::isError()
38      */
39     function Image_Transform_Driver_GD1()
40     {
41         $this->__construct();
42     } // End function Image
43
44     /**
45      * Check settings
46      *
47      * @return mixed true or  or a PEAR error object on error
48      *
49      * @see PEAR::isError()
50      */
51     function __construct()
52     {
53         parent::__construct();
54     } // End function Image
55
56    /**
57     * Resize Action
58     *
59     * For GD 2.01+ the new copyresampled function is used
60     * It uses a bicubic interpolation algorithm to get far
61     * better result.
62     *
63     * @param $new_x int  new width
64     * @param $new_y int  new height
65     * @param mixed $options Optional parameters
66     *
67     * @return true on success or PEAR Error object on error
68     * @see PEAR::isError()
69     */
70     function _resize($new_x, $new_y, $options = null)
71     {
72         if ($this->resized === true) {
73             return PEAR::raiseError('You have already resized the image without saving it.  Your previous resizing will be overwritten', null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);
74         }
75         $new_img =ImageCreate($new_x,$new_y);
76         ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
77         $this->old_image = $this->imageHandle;
78         $this->imageHandle = $new_img;
79         $this->resized = true;
80
81         $this->new_x = $new_x;
82         $this->new_y = $new_y;
83         return true;
84     }
85
86
87     function rotate($angle, $options = null)
88     {
89         if ($options == null){
90             $autoresize = true;
91             $color_mask = array(255,255,0);
92         } else {
93             extract($options);
94         }
95
96         while ($angle <= -45) {
97             $angle  += 360;
98         }
99         while ($angle > 270) {
100             $angle  -= 360;
101         }
102
103         $t = deg2rad($angle);
104
105         if (!is_array($color_mask)) {
106             // Not already in numberical format, so we convert it.
107             if ($color_mask{0} == '#'){
108                 $color_mask = $this->colorhex2colorarray($color_mask);
109             } else {
110                 include_once 'Image/Transform/Driver/ColorsDefs.php';
111                 $color_mask = isset($colornames[$color_mask])?$colornames[$color_mask]:false;
112             }
113         }
114
115         // Do not round it, too much lost of quality
116         $cosT   = cos($t);
117         $sinT   = sin($t);
118
119         $img    =& $this->imageHandle;
120
121         $width  = $max_x  = $this->img_x;
122         $height = $max_y  = $this->img_y;
123         $min_y  = 0;
124         $min_x  = 0;
125
126         $x1     = round($max_x/2,0);
127         $y1     = round($max_y/2,0);
128
129         if ( $autoresize ){
130             $t      = abs($t);
131             $a      = round($angle,0);
132             switch((int)($angle)){
133                 case 0:
134                         $width2     = $width;
135                         $height2    = $height;
136                     break;
137                 case 90:
138                         $width2     = $height;
139                         $height2    = $width;
140                     break;
141                 case 180:
142                         $width2     = $width;
143                         $height2    = $height;
144                     break;
145                 case 270:
146                         $width2     = $height;
147                         $height2    = $width;
148                     break;
149                 default:
150                     $width2     = (int)(abs(sin($t) * $height + cos($t) * $width));
151                     $height2    = (int)(abs(cos($t) * $height+sin($t) * $width));
152             }
153
154             $width2     -= $width2%2;
155             $height2    -= $height2%2;
156
157             $d_width    = abs($width - $width2);
158             $d_height   = abs($height - $height2);
159             $x_offset   = $d_width/2;
160             $y_offset   = $d_height/2;
161             $min_x2     = -abs($x_offset);
162             $min_y2     = -abs($y_offset);
163             $max_x2     = $width2;
164             $max_y2     = $height2;
165         }
166
167         $img2   = @imagecreateTrueColor($width2,$height2);
168
169         if (!is_resource($img2)) {
170             return PEAR::raiseError('Cannot create buffer for the rotataion.',
171                                 null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);
172         }
173
174         $this->img_x = $width2;
175         $this->img_y = $height2;
176
177
178         imagepalettecopy($img2,$img);
179
180         $mask   = imagecolorresolve($img2,$color_mask[0],$color_mask[1],$color_mask[2]);
181
182         // use simple lines copy for axes angles
183         switch ((int)($angle)) {
184             case 0:
185                 imagefill($img2, 0, 0,$mask);
186                 for ($y = 0; $y < $max_y; $y++) {
187                     for ($x = $min_x; $x < $max_x; $x++){
188                         $c  = @imagecolorat ( $img, $x, $y);
189                         imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
190                     }
191                 }
192                 break;
193             case 90:
194                 imagefill ($img2, 0, 0,$mask);
195                 for ($x = $min_x; $x < $max_x; $x++){
196                     for ($y=$min_y; $y < $max_y; $y++) {
197                         $c  = imagecolorat ( $img, $x, $y);
198                         imagesetpixel($img2,$max_y-$y-1,$x,$c);
199                     }
200                 }
201                 break;
202             case 180:
203                 imagefill ($img2, 0, 0,$mask);
204                 for ($y=0; $y < $max_y; $y++) {
205                     for ($x = $min_x; $x < $max_x; $x++){
206                         $c  = @imagecolorat ( $img, $x, $y);
207                         imagesetpixel($img2, $max_x2-$x-1, $max_y2-$y-1, $c);
208                     }
209                 }
210                 break;
211             case 270:
212                 imagefill ($img2, 0, 0,$mask);
213                 for ($y=0; $y < $max_y; $y++) {
214                     for ($x = $max_x; $x >= $min_x; $x--){
215                         $c  = @imagecolorat ( $img, $x, $y);
216                         imagesetpixel($img2,$y,$max_x-$x-1,$c);
217                     }
218                 }
219                 break;
220             // simple reverse rotation algo
221             default:
222                 $i=0;
223                 for ($y = $min_y2; $y < $max_y2; $y++){
224
225                     // Algebra :)
226                     $x2 = round((($min_x2-$x1) * $cosT) + (($y-$y1) * $sinT + $x1),0);
227                     $y2 = round((($y-$y1) * $cosT - ($min_x2-$x1) * $sinT + $y1),0);
228
229                     for ($x = $min_x2; $x < $max_x2; $x++){
230
231                         // Check if we are out of original bounces, if we are
232                         // use the default color mask
233                         if ( $x2>=0 && $x2<$max_x && $y2>=0 && $y2<$max_y ){
234                             $c  = imagecolorat ( $img, $x2, $y2);
235                         } else {
236                             $c  = $mask;
237                         }
238                         imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
239
240                         // round verboten!
241                         $x2  += $cosT;
242                         $y2  -= $sinT;
243                     }
244                 }
245                 break;
246         }
247
248         $this->imageHandle  =  $img2;
249         return true;
250     }
251 } // End class ImageGD