2004-04-21 22:43:23 +02:00
< ? php
/***********************************************************************
** Title .........: GD Driver
** Version .......: 1.0
** Author ........: Xiang Wei ZHUO < wei @ zhuo . org >
** Filename ......: GD . php
** Last changed ..: 30 Aug 2003
** Notes .........: Orginal is from PEAR
**/
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2002 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.02 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Peter Bowyer <peter@mapledesign.co.uk> |
// | Alan Knowles <alan@akbkhome.com> |
// +----------------------------------------------------------------------+
//
// Usage :
// $img = new Image_Transform_GD();
// $angle = -78;
// $img->load('magick.png');
//
// if($img->rotate($angle,array('autoresize'=>true,'color_mask'=>array(255,0,0)))){
// $img->addText(array('text'=>"Rotation $angle",'x'=>0,'y'=>100,'font'=>'/usr/share/fonts/default/TrueType/cogb____.ttf'));
// $img->display();
// } else {
// echo "Error";
// }
//
//
// $Id$
//
// Image Transformation interface using the GD library
//
require_once " Transform.php " ;
Class Image_Transform_Driver_GD extends Image_Transform
{
/**
* Holds the image file for manipulation
*/
var $imageHandle = '' ;
/**
* Holds the original image file
*/
var $old_image = '' ;
/**
* Check settings
*
* @ return mixed true or or a PEAR error object on error
*
* @ see PEAR :: isError ()
*/
function Image_Transform_GD ()
{
return ;
} // End function Image
/**
* Load image
*
* @ param string filename
*
* @ return mixed none or a PEAR error object on error
* @ see PEAR :: isError ()
*/
function load ( $image )
{
$this -> uid = md5 ( $_SERVER [ 'REMOTE_ADDR' ]);
2004-06-15 02:27:03 +02:00
$this -> image = $image ;
2004-04-21 22:43:23 +02:00
$this -> _get_image_details ( $image );
$functionName = 'ImageCreateFrom' . $this -> type ;
$this -> imageHandle = $functionName ( $this -> image );
} // End load
/**
* addText
*
* @ param array options Array contains options
* array (
* 'text' The string to draw
* 'x' Horizontal position
* 'y' Vertical Position
* 'Color' Font color
* 'font' Font to be used
* 'size' Size of the fonts in pixel
* 'resize_first' Tell if the image has to be resized
* before drawing the text
* )
*
* @ return none
* @ see PEAR :: isError ()
*/
function addText ( $params )
{
$default_params = array (
'text' => 'This is Text' ,
'x' => 10 ,
'y' => 20 ,
'color' => array ( 255 , 0 , 0 ),
'font' => 'Arial.ttf' ,
'size' => '12' ,
'angle' => 0 ,
'resize_first' => false // Carry out the scaling of the image before annotation? Not used for GD
);
$params = array_merge ( $default_params , $params );
extract ( $params );
if ( ! is_array ( $color ) ){
if ( $color [ 0 ] == '#' ){
$this -> colorhex2colorarray ( $color );
} else {
include_once ( 'Image/Transform/Driver/ColorsDefs.php' );
$color = isset ( $colornames [ $color ]) ? $colornames [ $color ] : false ;
}
}
$c = imagecolorresolve ( $this -> imageHandle , $color [ 0 ], $color [ 1 ], $color [ 2 ]);
if ( 'ttf' == substr ( $font , - 3 )) {
ImageTTFText ( $this -> imageHandle , $size , $angle , $x , $y , $c , $font , $text );
} else {
ImagePSText ( $this -> imageHandle , $size , $angle , $x , $y , $c , $font , $text );
}
return true ;
} // End addText
/**
* Rotate image by the given angle
* Uses a fast rotation algorythm for custom angles
* or lines copy for multiple of 90 degrees
*
* @ param int $angle Rotation angle
* @ param array $options array ( 'autoresize' => true | false ,
* 'color_mask' => array ( r , g , b ), named color or #rrggbb
* )
* @ author Pierre - Alain Joye
* @ return mixed none or a PEAR error object on error
* @ see PEAR :: isError ()
*/
function rotate ( $angle , $options = null )
{
if ( function_exists ( 'imagerotate' )) {
$white = imagecolorallocate ( $this -> imageHandle , 255 , 255 , 255 );
$this -> imageHandle = imagerotate ( $this -> imageHandle , $angle , $white );
return true ;
}
if ( $options == null ){
$autoresize = true ;
$color_mask = array ( 255 , 255 , 0 );
} else {
extract ( $options );
}
while ( $angle <= - 45 ) {
$angle += 360 ;
}
while ( $angle > 270 ) {
$angle -= 360 ;
}
$t = deg2rad ( $angle );
if ( ! is_array ( $color_mask ) ){
if ( $color [ 0 ] == '#' ){
$this -> colorhex2colorarray ( $color_mask );
} else {
include_once ( 'Image/Transform/Driver/ColorDefs.php' );
$color = isset ( $colornames [ $color_mask ]) ? $colornames [ $color_mask ] : false ;
}
}
// Do not round it, too much lost of quality
$cosT = cos ( $t );
$sinT = sin ( $t );
$img =& $this -> imageHandle ;
$width = $max_x = $this -> img_x ;
$height = $max_y = $this -> img_y ;
$min_y = 0 ;
$min_x = 0 ;
$x1 = round ( $max_x / 2 , 0 );
$y1 = round ( $max_y / 2 , 0 );
if ( $autoresize ){
$t = abs ( $t );
$a = round ( $angle , 0 );
switch (( int )( $angle )){
case 0 :
$width2 = $width ;
$height2 = $height ;
break ;
case 90 :
$width2 = $height ;
$height2 = $width ;
break ;
case 180 :
$width2 = $width ;
$height2 = $height ;
break ;
case 270 :
$width2 = $height ;
$height2 = $width ;
break ;
default :
$width2 = ( int )( abs ( sin ( $t ) * $height + cos ( $t ) * $width ));
$height2 = ( int )( abs ( cos ( $t ) * $height + sin ( $t ) * $width ));
}
$width2 -= $width2 % 2 ;
$height2 -= $height2 % 2 ;
$d_width = abs ( $width - $width2 );
$d_height = abs ( $height - $height2 );
$x_offset = $d_width / 2 ;
$y_offset = $d_height / 2 ;
$min_x2 = - abs ( $x_offset );
$min_y2 = - abs ( $y_offset );
$max_x2 = $width2 ;
$max_y2 = $height2 ;
}
$img2 = @ imagecreate ( $width2 , $height2 );
if ( ! is_resource ( $img2 ) ){
return false ; /* PEAR :: raiseError ( 'Cannot create buffer for the rotataion.' ,
null , PEAR_ERROR_TRIGGER , E_USER_NOTICE ); */
}
$this -> img_x = $width2 ;
$this -> img_y = $height2 ;
imagepalettecopy ( $img2 , $img );
$mask = imagecolorresolve ( $img2 , $color_mask [ 0 ], $color_mask [ 1 ], $color_mask [ 2 ]);
// use simple lines copy for axes angles
switch (( int )( $angle )){
case 0 :
imagefill ( $img2 , 0 , 0 , $mask );
for ( $y = 0 ; $y < $max_y ; $y ++ ) {
for ( $x = $min_x ; $x < $max_x ; $x ++ ){
$c = @ imagecolorat ( $img , $x , $y );
imagesetpixel ( $img2 , $x + $x_offset , $y + $y_offset , $c );
}
}
break ;
case 90 :
imagefill ( $img2 , 0 , 0 , $mask );
for ( $x = $min_x ; $x < $max_x ; $x ++ ){
for ( $y = $min_y ; $y < $max_y ; $y ++ ) {
$c = imagecolorat ( $img , $x , $y );
imagesetpixel ( $img2 , $max_y - $y - 1 , $x , $c );
}
}
break ;
case 180 :
imagefill ( $img2 , 0 , 0 , $mask );
for ( $y = 0 ; $y < $max_y ; $y ++ ) {
for ( $x = $min_x ; $x < $max_x ; $x ++ ){
$c = @ imagecolorat ( $img , $x , $y );
imagesetpixel ( $img2 , $max_x2 - $x - 1 , $max_y2 - $y - 1 , $c );
}
}
break ;
case 270 :
imagefill ( $img2 , 0 , 0 , $mask );
for ( $y = 0 ; $y < $max_y ; $y ++ ) {
for ( $x = $max_x ; $x >= $min_x ; $x -- ){
$c = @ imagecolorat ( $img , $x , $y );
imagesetpixel ( $img2 , $y , $max_x - $x - 1 , $c );
}
}
break ;
// simple reverse rotation algo
default :
$i = 0 ;
for ( $y = $min_y2 ; $y < $max_y2 ; $y ++ ){
// Algebra :)
$x2 = round ((( $min_x2 - $x1 ) * $cosT ) + (( $y - $y1 ) * $sinT + $x1 ), 0 );
$y2 = round ((( $y - $y1 ) * $cosT - ( $min_x2 - $x1 ) * $sinT + $y1 ), 0 );
for ( $x = $min_x2 ; $x < $max_x2 ; $x ++ ){
// Check if we are out of original bounces, if we are
// use the default color mask
if ( $x2 >= 0 && $x2 < $max_x && $y2 >= 0 && $y2 < $max_y ){
$c = imagecolorat ( $img , $x2 , $y2 );
} else {
$c = $mask ;
}
imagesetpixel ( $img2 , $x + $x_offset , $y + $y_offset , $c );
// round verboten!
$x2 += $cosT ;
$y2 -= $sinT ;
}
}
break ;
}
$this -> old_image = $this -> imageHandle ;
$this -> imageHandle = $img2 ;
return true ;
}
/**
* Resize Action
*
* For GD 2.01 + the new copyresampled function is used
* It uses a bicubic interpolation algorithm to get far
* better result .
*
* @ param $new_x int new width
* @ param $new_y int new height
*
* @ return true on success or pear error
* @ see PEAR :: isError ()
*/
function _resize ( $new_x , $new_y ) {
if ( $this -> resized === true ) {
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);*/
}
if ( function_exists ( 'ImageCreateTrueColor' )){
$new_img = ImageCreateTrueColor ( $new_x , $new_y );
} else {
$new_img = ImageCreate ( $new_x , $new_y );
}
if ( function_exists ( 'ImageCopyResampled' )){
ImageCopyResampled ( $new_img , $this -> imageHandle , 0 , 0 , 0 , 0 , $new_x , $new_y , $this -> img_x , $this -> img_y );
} else {
ImageCopyResized ( $new_img , $this -> imageHandle , 0 , 0 , 0 , 0 , $new_x , $new_y , $this -> img_x , $this -> img_y );
}
$this -> old_image = $this -> imageHandle ;
$this -> imageHandle = $new_img ;
$this -> resized = true ;
$this -> new_x = $new_x ;
$this -> new_y = $new_y ;
return true ;
}
/**
* Crop the image
*
* @ param int $crop_x left column of the image
* @ param int $crop_y top row of the image
* @ param int $crop_width new cropped image width
* @ param int $crop_height new cropped image height
*/
function crop ( $new_x , $new_y , $new_width , $new_height )
{
if ( function_exists ( 'ImageCreateTrueColor' )){
$new_img = ImageCreateTrueColor ( $new_width , $new_height );
} else {
$new_img = ImageCreate ( $new_width , $new_height );
}
if ( function_exists ( 'ImageCopyResampled' )){
ImageCopyResampled ( $new_img , $this -> imageHandle , 0 , 0 , $new_x , $new_y , $new_width , $new_height , $new_width , $new_height );
} else {
ImageCopyResized ( $new_img , $this -> imageHandle , 0 , 0 , $new_x , $new_y , $new_width , $new_height , $new_width , $new_height );
}
$this -> old_image = $this -> imageHandle ;
$this -> imageHandle = $new_img ;
$this -> resized = true ;
$this -> new_x = $new_x ;
$this -> new_y = $new_y ;
return true ;
}
/**
* Flip the image horizontally or vertically
*
* @ param boolean $horizontal true if horizontal flip , vertical otherwise
*/
function flip ( $horizontal )
{
if ( ! $horizontal ) {
$this -> rotate ( 180 );
}
$width = imagesx ( $this -> imageHandle );
$height = imagesy ( $this -> imageHandle );
for ( $j = 0 ; $j < $height ; $j ++ ) {
$left = 0 ;
$right = $width - 1 ;
while ( $left < $right ) {
//echo " j:".$j." l:".$left." r:".$right."\n<br>";
$t = imagecolorat ( $this -> imageHandle , $left , $j );
imagesetpixel ( $this -> imageHandle , $left , $j , imagecolorat ( $this -> imageHandle , $right , $j ));
imagesetpixel ( $this -> imageHandle , $right , $j , $t );
$left ++ ; $right -- ;
}
}
return true ;
}
/**
* Adjust the image gamma
*
* @ param float $outputgamma
*
* @ return none
*/
function gamma ( $outputgamma = 1.0 ) {
ImageGammaCorrect ( $this -> imageHandle , 1.0 , $outputgamma );
}
/**
* Save the image file
*
* @ param $filename string the name of the file to write to
* @ param $quality int output DPI , default is 85
* @ param $types string define the output format , default
* is the current used format
*
* @ return none
*/
function save ( $filename , $type = '' , $quality = 85 )
{
$type = $type == '' ? $this -> type : $type ;
$functionName = 'image' . $type ;
$this -> old_image = $this -> imageHandle ;
$functionName ( $this -> imageHandle , $filename ) ;
$this -> imageHandle = $this -> old_image ;
$this -> resized = false ;
} // End save
/**
* Display image without saving and lose changes
*
* @ param string type ( JPG , PNG ... );
* @ param int quality 75
*
* @ return none
*/
function display ( $type = '' , $quality = 75 )
{
if ( $type != '' ) {
$this -> type = $type ;
}
$functionName = 'Image' . $this -> type ;
header ( 'Content-type: image/' . strtolower ( $this -> type ));
$functionName ( $this -> imageHandle , '' , $quality );
$this -> imageHandle = $this -> old_image ;
$this -> resized = false ;
ImageDestroy ( $this -> old_image );
$this -> free ();
}
/**
* Destroy image handle
*
* @ return none
*/
function free ()
{
if ( $this -> imageHandle ){
ImageDestroy ( $this -> imageHandle );
}
}
} // End class ImageGD
?>