source: trunk/plugins/ImageManager/Classes/GD.php @ 937

Last change on this file since 937 was 937, checked in by ray, 12 years ago

#1132 [ExtendedFileManager?] new Version

  • Property svn:keywords set to LastChangedDate LastChangedRevision LastChangedBy HeadURL Id
File size: 19.7 KB
RevLine 
[43]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//
[677]40// $Id$
[43]41//
42// Image Transformation interface using the GD library
43//
44
[709]45require_once "../ImageManager/Classes/Transform.php";
[43]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;
[937]85               
[43]86                if(function_exists($functionName))
87                {
88                        $this->imageHandle = $functionName($this->image);
[937]89                        if ( $this->type == 'png')
90                        {
91                                imageAlphaBlending($this->imageHandle, false);
92                                imageSaveAlpha($this->imageHandle, true);
93                        }
[43]94                }
95    } // End load
96
97    /**
98     * addText
99     *
100     * @param   array   options     Array contains options
101     *                              array(
102     *                                  'text'  The string to draw
103     *                                  'x'     Horizontal position
104     *                                  'y'     Vertical Position
105     *                                  'Color' Font color
106     *                                  'font'  Font to be used
107     *                                  'size'  Size of the fonts in pixel
108     *                                  'resize_first'  Tell if the image has to be resized
109     *                                                  before drawing the text
110     *                              )
111     *
112     * @return none
113     * @see PEAR::isError()
114     */
115    function addText($params)
116    {
117        $default_params = array(
118                                'text' => 'This is Text',
119                                'x' => 10,
120                                'y' => 20,
121                                'color' => array(255,0,0),
122                                'font' => 'Arial.ttf',
123                                'size' => '12',
124                                'angle' => 0,
125                                'resize_first' => false // Carry out the scaling of the image before annotation?  Not used for GD
126                                );
127        $params = array_merge($default_params, $params);
128        extract($params);
129
130        if( !is_array($color) ){
131            if ($color[0]=='#'){
132                $this->colorhex2colorarray( $color );
133            } else {
134                include_once('Image/Transform/Driver/ColorsDefs.php');
135                $color = isset($colornames[$color])?$colornames[$color]:false;
136            }
137        }
138
139        $c = imagecolorresolve ($this->imageHandle, $color[0], $color[1], $color[2]);
140
141        if ('ttf' == substr($font, -3)) {
142            ImageTTFText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
143        } else {
144            ImagePSText($this->imageHandle, $size, $angle, $x, $y, $c, $font, $text);
145        }
146        return true;
147    } // End addText
148
149
150    /**
151     * Rotate image by the given angle
152     * Uses a fast rotation algorythm for custom angles
153     * or lines copy for multiple of 90 degrees
154     *
155     * @param int       $angle      Rotation angle
156     * @param array     $options    array(  'autoresize'=>true|false,
157     *                                      'color_mask'=>array(r,g,b), named color or #rrggbb
158     *                                   )
159     * @author Pierre-Alain Joye
160     * @return mixed none or a PEAR error object on error
161     * @see PEAR::isError()
162     */
163    function rotate($angle, $options=null)
164    {
165        if(function_exists('imagerotate')) {
[937]166            $white = imagecolorallocatealpha ($this->imageHandle, 255, 255, 255, 127);
[43]167                        $this->imageHandle = imagerotate($this->imageHandle, $angle, $white);
168            return true;
169        }
170
171        if ( $options==null ){
172            $autoresize = true;
[937]173            $color_mask = array(105,255,255);
[43]174        } else {
175            extract( $options );
176        }
177
178        while ($angle <= -45) {
179            $angle  += 360;
180        }
181        while ($angle > 270) {
182            $angle  -= 360;
183        }
184
185        $t      = deg2rad($angle);
186
187        if( !is_array($color_mask) ){
188            if ($color[0]=='#'){
189                $this->colorhex2colorarray( $color_mask );
190            } else {
191                include_once('Image/Transform/Driver/ColorDefs.php');
192                $color = isset($colornames[$color_mask])?$colornames[$color_mask]:false;
193            }
194        }
195
196        // Do not round it, too much lost of quality
197        $cosT   = cos($t);
198        $sinT   = sin($t);
199
200        $img    =& $this->imageHandle;
201
202        $width  = $max_x  = $this->img_x;
203        $height = $max_y  = $this->img_y;
204        $min_y  = 0;
205        $min_x  = 0;
206
207        $x1     = round($max_x/2,0);
208        $y1     = round($max_y/2,0);
209
210        if ( $autoresize ){
211            $t      = abs($t);
212            $a      = round($angle,0);
213            switch((int)($angle)){
214                case 0:
215                        $width2     = $width;
216                        $height2    = $height;
217                    break;
218                case 90:
219                        $width2     = $height;
220                        $height2    = $width;
221                    break;
222                case 180:
223                        $width2     = $width;
224                        $height2    = $height;
225                    break;
226                case 270:
227                        $width2     = $height;
228                        $height2    = $width;
229                    break;
230                default:
231                    $width2     = (int)(abs(sin($t) * $height + cos($t) * $width));
232                    $height2    = (int)(abs(cos($t) * $height+sin($t) * $width));
233            }
234
235            $width2     -= $width2%2;
236            $height2    -= $height2%2;
237
238            $d_width    = abs($width - $width2);
239            $d_height   = abs($height - $height2);
240            $x_offset   = $d_width/2;
241            $y_offset   = $d_height/2;
242            $min_x2     = -abs($x_offset);
243            $min_y2     = -abs($y_offset);
244            $max_x2     = $width2;
245            $max_y2     = $height2;
246        }
247
[937]248        $img2   = @$this->newImgPreserveAlpha( imagecreateTrueColor($width2,$height2) );
[43]249
250        if ( !is_resource($img2) ){
251            return false;/*PEAR::raiseError('Cannot create buffer for the rotataion.',
252                                null, PEAR_ERROR_TRIGGER, E_USER_NOTICE);*/
253        }
254
255        $this->img_x = $width2;
256        $this->img_y = $height2;
257
258
259        imagepalettecopy($img2,$img);
260
[937]261       $mask = imagecolorallocatealpha ($img2,$color_mask[0],$color_mask[1],$color_mask[2],127);
[43]262        // use simple lines copy for axes angles
263        switch((int)($angle)){
264            case 0:
265                imagefill ($img2, 0, 0,$mask);
266                for ($y=0; $y < $max_y; $y++) {
267                    for ($x = $min_x; $x < $max_x; $x++){
268                        $c  = @imagecolorat ( $img, $x, $y);
269                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
270                    }
271                }
272                break;
273            case 90:
274                imagefill ($img2, 0, 0,$mask);
275                for ($x = $min_x; $x < $max_x; $x++){
276                    for ($y=$min_y; $y < $max_y; $y++) {
277                        $c  = imagecolorat ( $img, $x, $y);
278                        imagesetpixel($img2,$max_y-$y-1,$x,$c);
279                    }
280                }
281                break;
282            case 180:
283                imagefill ($img2, 0, 0,$mask);
284                for ($y=0; $y < $max_y; $y++) {
285                    for ($x = $min_x; $x < $max_x; $x++){
286                        $c  = @imagecolorat ( $img, $x, $y);
287                        imagesetpixel($img2, $max_x2-$x-1, $max_y2-$y-1, $c);
288                    }
289                }
290                break;
291            case 270:
292                imagefill ($img2, 0, 0,$mask);
293                for ($y=0; $y < $max_y; $y++) {
294                    for ($x = $max_x; $x >= $min_x; $x--){
295                        $c  = @imagecolorat ( $img, $x, $y);
296                        imagesetpixel($img2,$y,$max_x-$x-1,$c);
297                    }
298                }
299                break;
300            // simple reverse rotation algo
301            default:
302                $i=0;
303                for ($y = $min_y2; $y < $max_y2; $y++){
304
305                    // Algebra :)
306                    $x2 = round((($min_x2-$x1) * $cosT) + (($y-$y1) * $sinT + $x1),0);
307                    $y2 = round((($y-$y1) * $cosT - ($min_x2-$x1) * $sinT + $y1),0);
308
309                    for ($x = $min_x2; $x < $max_x2; $x++){
310
311                        // Check if we are out of original bounces, if we are
312                        // use the default color mask
313                        if ( $x2>=0 && $x2<$max_x && $y2>=0 && $y2<$max_y ){
314                            $c  = imagecolorat ( $img, $x2, $y2);
315                        } else {
316                            $c  = $mask;
317                        }
318                        imagesetpixel($img2,$x+$x_offset,$y+$y_offset,$c);
319
320                        // round verboten!
321                        $x2  += $cosT;
322                        $y2  -= $sinT;
323                    }
324                }
325                break;
326        }
327        $this->old_image    = $this->imageHandle;
328        $this->imageHandle  =  $img2;
329        return true;
330    }
331
332
333   /**
334    * Resize Action
335    *
336    * For GD 2.01+ the new copyresampled function is used
337    * It uses a bicubic interpolation algorithm to get far
338    * better result.
339    *
[447]340    * @param int  $new_x new width
341    * @param int  $new_y new height
[43]342    *
343    * @return true on success or pear error
344    * @see PEAR::isError()
345    */
346    function _resize($new_x, $new_y) {
347        if ($this->resized === true) {
348            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);*/
349        }
350        if(function_exists('ImageCreateTrueColor')){
[937]351           $new_img = $this->newImgPreserveAlpha( ImageCreateTrueColor($new_x,$new_y) );
[43]352        } else {
353            $new_img =ImageCreate($new_x,$new_y);
354        }
[937]355
[43]356        if(function_exists('ImageCopyResampled')){
357            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
358        } else {
359            ImageCopyResized($new_img, $this->imageHandle, 0, 0, 0, 0, $new_x, $new_y, $this->img_x, $this->img_y);
360        }
[937]361
[43]362        $this->old_image = $this->imageHandle;
363        $this->imageHandle = $new_img;
364        $this->resized = true;
365
366        $this->new_x = $new_x;
367        $this->new_y = $new_y;
368        return true;
369    }
370
371    /**
372     * Crop the image
373     *
374     * @param int $crop_x left column of the image
375     * @param int $crop_y top row of the image
376     * @param int $crop_width new cropped image width
377     * @param int $crop_height new cropped image height
378     */
379    function crop($new_x, $new_y, $new_width, $new_height)
380    {
381        if(function_exists('ImageCreateTrueColor')){
[937]382            $new_img =  $this->newImgPreserveAlpha(ImageCreateTrueColor($new_width,$new_height));
[43]383        } else {
384            $new_img =ImageCreate($new_width,$new_height);
385        }
386        if(function_exists('ImageCopyResampled')){
387            ImageCopyResampled($new_img, $this->imageHandle, 0, 0, $new_x, $new_y,$new_width,$new_height,$new_width,$new_height);
388        } else {
389            ImageCopyResized($new_img, $this->imageHandle, 0, 0, $new_x, $new_y, $new_width,$new_height,$new_width,$new_height);
390        }
391        $this->old_image = $this->imageHandle;
392        $this->imageHandle = $new_img;
393        $this->resized = true;
394
395        $this->new_x = $new_x;
396        $this->new_y = $new_y;
397        return true;
398    }
399   
400    /**
401     * Flip the image horizontally or vertically
402     *
403     * @param boolean $horizontal true if horizontal flip, vertical otherwise
404     */
405    function flip($horizontal)
406    {
407        if(!$horizontal) {
408            $this->rotate(180);
409        }
410
411        $width = imagesx($this->imageHandle);
412        $height = imagesy($this->imageHandle);
413
414        for ($j = 0; $j < $height; $j++) {
415                $left = 0;
416                $right = $width-1;
417
418
419                while ($left < $right) {
420                    //echo " j:".$j." l:".$left." r:".$right."\n<br>";
421                    $t = imagecolorat($this->imageHandle, $left, $j);
422                    imagesetpixel($this->imageHandle, $left, $j, imagecolorat($this->imageHandle, $right, $j));
423                    imagesetpixel($this->imageHandle, $right, $j, $t);
424                    $left++; $right--;
425                }
426           
427        }
428
429        return true;
430    }
431
432
433    /**
434     * Adjust the image gamma
435     *
436     * @param float $outputgamma
437     *
438     * @return none
439     */
440    function gamma($outputgamma=1.0) {
441        ImageGammaCorrect($this->imageHandle, 1.0, $outputgamma);
442    }
[937]443        function paletteToTrueColorWithTransparency()
444        {
445                $oldImg = $this->imageHandle;
446                $newImg = $this->newImgPreserveAlpha( imagecreatetruecolor($this->img_x,$this->img_y) );
447                imagecopy($newImg,$oldImg,0,0,0,0,$this->img_x,$this->img_y);
[43]448
[937]449                $this->imageHandle = $newImg;
450        }
451       
452        function newImgPreserveAlpha($newImg)
453        {
454                if ( $this->type == 'jpeg') return $newImg;
455               
456                // Turn off transparency blending (temporarily)
457                imagealphablending($newImg, false);
458               
459                // Create a new transparent color for image
460                if ( $transparent = imagecolortransparent($this->imageHandle) >= 0 )
461                {
462                        if (imageistruecolor($this->imageHandle))
463                        {
464                                $red = ($transparent & 0xFF0000) >> 16;
465                                $green = ($transparent & 0x00FF00) >> 8;
466                                $blue = ($transparent & 0x0000FF);
467                                $color_values = array('red' => $red, 'green' => $green, 'blue' => $blue);
468                        }
469                        else
470                        {
471                                $color_values = imagecolorsforindex($this->imageHandle,$transparent);
472
473                        }
474                        $color_values = imagecolorsforindex($this->imageHandle,$transparent);
475                        $color = imagecolorallocatealpha($newImg, $color_values['red'],$color_values['green'],$color_values['blue'], 127);
476                        $colort = imagecolorallocate($newImg, $color_values['red'],$color_values['green'],$color_values['blue']);
477                }
478                else
479                {
480                        $color = imagecolorallocatealpha($newImg, 252, 2, 252, 127);
481                        $colort = imagecolorallocate($newImg, 252, 2, 252);
482                }
483                imagecolortransparent($newImg,$colort);
484               
485                // Completely fill the background of the new image with allocated color.
486                imagefill($newImg, 0, 0, $color);
487               
488                // Restore transparency blending
489                imagesavealpha($newImg, true);
490               
491                return $newImg;
492        }
493       
494        function preserveTransparencyForPalette()
495        {
496                $new_img = imagecreatetruecolor($this->img_x,$this->img_y);
497                $truecolor = imageistruecolor($this->imageHandle);
498                $transparent = imagecolorallocate($new_img, 252,2,252); // nasty pinkish purple that hopefully doesn't exist in the image
499
500                imagecolortransparent($new_img, $transparent);
501                for ($i=0;$i<$this->img_y;$i++)
502                {
503                        for ($j=0;$j<$this->img_x;$j++)
504                        {
505                                $c = imagecolorat($this->imageHandle,$j, $i);
506                                if ($truecolor)
507                                {
508                                        $a = ($c >> 24) & 0xFF;
509                                        $r = ($c >> 16) & 0xFF;
510                                        $g = ($c >> 8) & 0xFF;
511                                        $b = $c & 0xFF;
512                                        $color_values = array('red' => $r, 'green' => $g, 'blue' => $b, 'alpha' => $a);
513                                }
514                                else
515                                {
516                                        $color_values = imagecolorsforindex($this->imageHandle,$transparent);
517                                }
518                                if ($color_values['alpha'] >= 126)
519                                {
520                                        imagesetpixel($new_img, $j, $i, $transparent);
521                                }
522                                else
523                                {
524                                        imagesetpixel($new_img, $j, $i, $c);
525                                }
526                        }
527                }
528                $this->imageHandle = $new_img;
529        }
530
[43]531    /**
532     * Save the image file
533     *
[447]534     * @param string  $filename the name of the file to write to
535     * @param int     $quality  output DPI, default is 85
536     * @param string  $types    define the output format, default
[43]537     *                          is the current used format
538     *
539     * @return none
540     */
541    function save($filename, $type = '', $quality = 85)
542    {
543                $type           = $type==''? $this->type : $type;
544                $functionName   = 'image' . $type;
545
546                if(function_exists($functionName))
547                {
548                        $this->old_image = $this->imageHandle;
549                        if($type=='jpeg')
550                                $functionName($this->imageHandle, $filename, $quality);
551                        else
552                                $functionName($this->imageHandle, $filename);
553                        $this->imageHandle = $this->old_image;
554                        $this->resized = false;
555                }
556    } // End save
557
558
559    /**
560     * Display image without saving and lose changes
561     *
562     * @param string type (JPG,PNG...);
563     * @param int quality 75
564     *
565     * @return none
566     */
567    function display($type = '', $quality = 75)
568    {
569        if ($type != '') {
570            $this->type = $type;
571        }
572        $functionName = 'Image' . $this->type;
573                if(function_exists($functionName))
574                {
575                        header('Content-type: image/' . strtolower($this->type));
576                        $functionName($this->imageHandle, '', $quality);
577                        $this->imageHandle = $this->old_image;
578                        $this->resized = false;
579                        ImageDestroy($this->old_image);
580                        $this->free();
581                }
582    }
583
584    /**
585     * Destroy image handle
586     *
587     * @return none
588     */
589    function free()
590    {
591        if ($this->imageHandle){
592            ImageDestroy($this->imageHandle);
593        }
594    }
595
596} // End class ImageGD
597?>
Note: See TracBrowser for help on using the repository browser.