Location: PHPKode > scripts > Imager > imager.php
<?php
abstract class imgLoaderSaver {
	protected $filename;
	abstract public function load( );
	abstract public function save( &$imgres );
}

class JPEG extends imgLoaderSaver {
	protected $quality = 85;

	public function __construct( $filename, $quality = 85 ) {
		$this->filename = $filename;
		$this->quality = $quality;
	}

	public function load( ) {
		if ( file_exists( $this->filename ) ) {
			return imagecreatefromjpeg( $this->filename );
		}
		return null;
	}
	
	public  function save( &$imgres ) {
		if ( !file_exists( $this->filename ) ) {
			imagejpeg( $imgres, $this->filename, $this->quality );
		} else {
			/* throw error */
		}
	}
}

class PNG extends imgLoaderSaver {
	protected $quality = 6;

	public function __construct( $filename, $quality = 6 ) {
		$this->filename = $filename;
		$this->quality = $quality;
	}

	public function load( ) {
		if ( file_exists( $this->filename ) ) {
			$res = imagecreatefrompng( $this->filename );
			return $res;
		} 
		return null;
	}
	
	public  function save( &$imgres ) {
		if ( !file_exists( $this->filename ) ) {
			imagepng( $imgres, $this->filename, $this->quality );
		} else {
			/* throw error */
		}
	}
}

class GIF extends imgLoaderSaver {
	public function __construct( $filename ) {
		$this->filename = $filename;
	}

	public function load( ) {
		if ( file_exists( $this->filename ) ) {
			return imagecreatefromgif( $this->filename );
		} 
		return null;
	}
	
	public  function save( &$imgres ) {
		if ( !file_exists( $this->filename ) ) {
			imagegif( $imgres, $this->filename );
		} else {
			/* throw error */
		}
	}
}

class Canvas extends imgLoaderSaver {
	protected $width  = 0;
	protected $height = 0;
	protected $color  = 0;
	
	public function __construct( $width, $height, $fillcolor = array( 0, 0, 0) ) {
		$this->width = $width;
		$this->height= $height;
		$this->color = $fillcolor;
	}

	public function load( ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		$col = imagecolorallocate( $t, $this->color[0], $this->color[1], $this->color[2] );
		imagefilledrectangle( $t, 0, 0, $this->width, $this->height, $col );
		return $t;
	}

	public  function save( &$imgres ) {
	}
}

class Transparency {
	public $transparent = false;
	public $alphachannel = false;
	public $color = array( 255, 255, 255 );

	public function __construct( $typeof = null ) {
		if ( $typeof != null ) {
			if ( is_array( $typeof ) ) {
				$this->transparent = true;
				$this->color = $typeof;
			} else if ( is_bool( $typeof ) ) {
				$this->transparent = true;
				$this->alphachannel = true;
			}
		}
	}
}

class Imager {
	const TOP_LEFT     = 0x00000001;
	const TOP_RIGHT    = 0x00000002;
	const BOTTOM_LEFT  = 0x00000003;
	const BOTTOM_RIGHT = 0x00000004;
	const CENTER       = 0x00000005;

	protected $properties = array( 'width', 'height' );
	protected $imgres = null;
	protected $transparencyinfo = null;

	private function rotateX( $x, $y, $theta ){
		return $x * cos( $theta ) - $y * sin( $theta );
	}

	private function rotateY( $x, $y, $theta ){
		return $x * sin( $theta ) + $y * cos( $theta );
	}

	public function __get( $k ) {
		if( array_key_exists( $k, $this->properties ) )
			return $this->properties[ $k ];
	}

	public function __set($k, $v) {
		$this->properties[$k] = $v;
	}
	
	public function getResource() {
		return $this->imgres;
	}
	
	public function getTransparencyInfo() {
		return $this->transparencyinfo;
	}

	public function __construct( $img = null, Transparency $transp = null ) {
		$this->transparencyinfo = $transp;
		if ( !is_null( $img ) ) {
			if ( $img instanceof Imager ) {
				$this->imgres = clone $img->getResource();
			} else if( $img instanceof imgLoaderSaver )  {
				$this->imgres = $img->load();
			} else if ( is_resource( $img ) ) {
				$this->imgres = $img;
			}
			if ( $this->imgres != null ) {
				$this->width  = imagesx( $this->imgres );
				$this->height = imagesy( $this->imgres );
			} else {
				/* throw an error */
			}
			if ( $transp != null ) {
				if ( $transp->transparent ) {
					if ( $transp->alphachannel ) {
						imagealphablending( $this->imgres, true );
						imagesavealpha( $this->imgres, true );
					} else {
						list( $r, $g, $b ) = $transp->color;
						$clr = imagecolorallocate( $this->imgres, $r, $g, $b);
						imagecolortransparent( $this->imgres, $clr );
					}
				}
			}
		} else {
			/* throw an error */
		}
	}

	function __destruct() {
		if ( is_resource( $this->imgres ) )
			imagedestroy( $this->imgres );
	}
	
	function save( $img = null ) {
		if ( !is_null( $img ) ) {
			if ( $img instanceof Imager ) {
				
			} else if( $img instanceof imgLoaderSaver ) {
				imagealphablending( $this->imgres, false );
				imagesavealpha( $this->imgres, true );
				$img->save( $this->imgres );
			} else {
				/* throw an error */
			}
		} else {
			/* throw an error */
		}
		
		return $this;
	}

	function fill( $color = array( 0, 0, 0 ) ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		$co = imagecolorallocate( $t, $color[0], $color[1], $color[2] );
		imagefilledrectangle( $t, 0, 0, $this->width, $this->height, $co );
		return new Imager( $t );
	}
	
	function thumb( $img ) {
		if ( ! ($img instanceof Imager) ) $img = new Imager( $img );

		$scale = min( $this->height / $img->height, $this->width / $img->width );
		$nw = (int)ceil( $img->width  * $scale );
		$nh = (int)ceil( $img->height * $scale );

		while ( $nw > $this->width  ) $nw--;
		while ( $nh > $this->height ) $nh--;

		return $this->watermark( $img->resize( $nw, $nh ), Imager::CENTER );
	}
	
	function addAlpha( $img ) {
		if ( ! ($img instanceof Imager) ) $img = new Imager( $img );
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagealphablending( $t, false );

		$alphid = $img->getResource();
		$tid = $this->getResource();
		for($y=0; $y< $this->height; $y++) {
			for($x=0; $x< $this->width; $x++) {
				$alpha = 127 - (int)( ( imagecolorat( $alphid, $x, $y ) & 0xFF ) / 2 );
				$rgb = imagecolorat( $tid, $x, $y );
				$r = ( $rgb >> 16 ) & 0xFF;
				$g = ( $rgb >> 8 ) & 0xFF;
				$b = $rgb & 0xFF;
				$color = imagecolorallocatealpha( $t, $r, $g, $b, $alpha );
				imagesetpixel( $t, $x, $y, $color );
			}
		}
		return new Imager( $t, new Transparency( true ) );
	}

	function resize( $width, $height ) {
		$t = imagecreatetruecolor( $width, $height );
		imagecopyresampled( $t, $this->imgres, 0, 0, 0, 0, $width, $height, $this->width, $this->height );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function crop( $x, $y, $w, $h ) {
		if($x + $w > $this->width) $w = $this->width - $x;
		if($y + $h > $this->height) $h = $this->height - $y;
		if($w <= 0 || $h <= 0) return false;

		$t = imagecreatetruecolor($w, $h);
		imagecopyresampled($t, $this->imgres, 0, 0, $x, $y, $this->width, $this->height, $this->width, $this->height);
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function flipH() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopyresampled( $t, $this->imgres, 0, 0, ($this->width-1), 0, $this->width, $this->height, 0-$this->width, $this->height );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function flipV() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopyresampled( $t, $this->imgres, 0, 0, 0, ($this->height-1), $this->width, $this->height, $this->width, 0-$this->height );
		return new Imager( $t, $this->getTransparencyInfo() );
	}
	
	function rotate( $degree, $color = array( 0,0,0 ) ) {
		$backcolor = $color[0] << 16 + $color[1] << 8 + $color[2];
		$t = imagerotate( $this->imgres, $degree, $backcolor );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	/* very slow (getpixel, setpixel), but correct alternative to rotate pic ( source from internet ) */
	function rotate2( $degree, $color = array( 0, 0, 0 ) ) {
		$srcImg = $this->imgres;
		$angle = $degree;
		$bgcolor = $color[0] << 16 + $color[1] << 8 + $color[2];
		$ignore_transparent = 0;
		$srcw = imagesx($srcImg);
		$srch = imagesy($srcImg);

		$angle %= 360;
		$angle = -$angle;

		if($angle == 0) {
			if ($ignore_transparent == 0) {
				imagesavealpha($srcImg, true);
			}
			return $srcImg;
		}

		$theta = deg2rad ($angle);

		if ( (abs($angle) == 90) || (abs($angle) == 270) ) {
			$width = $srch;
			$height = $srcw;
			if ( ($angle == 90) || ($angle == -270) ) {
				$minX = 0;
				$maxX = $width;
				$minY = -$height+1;
				$maxY = 1;
			} else if ( ($angle == -90) || ($angle == 270) ) {
				$minX = -$width+1;
				$maxX = 1;
				$minY = 0;
				$maxY = $height;
			}
		} else if (abs($angle) === 180) {
			$width = $srcw;
			$height = $srch;
			$minX = -$width+1;
			$maxX = 1;
			$minY = -$height+1;
			$maxY = 1;
		} else {
			$temp = array (rotateX(0, 0, 0-$theta),
				rotateX($srcw, 0, 0-$theta),
				rotateX(0, $srch, 0-$theta),
				rotateX($srcw, $srch, 0-$theta)
			);
			$minX = floor(min($temp));
			$maxX = ceil(max($temp));
			$width = $maxX - $minX;

			// the height of the destination image.
			$temp = array (rotateY(0, 0, 0-$theta),
				rotateY($srcw, 0, 0-$theta),
				rotateY(0, $srch, 0-$theta),
				rotateY($srcw, $srch, 0-$theta)
			);
			$minY = floor(min($temp));
			$maxY = ceil(max($temp));
			$height = $maxY - $minY;
		}

		$destimg = imagecreatetruecolor($width, $height);
		if ($ignore_transparent == 0) {
			imagefill($destimg, 0, 0, imagecolorallocatealpha($destimg, 255,255, 255, 127));
			imagesavealpha($destimg, true);
		}

		for($x=$minX; $x<$maxX; $x++) {
			for($y=$minY; $y<$maxY; $y++) {
				// fetch corresponding pixel from the source image
				$srcX = round(rotateX($x, $y, $theta));
				$srcY = round(rotateY($x, $y, $theta));
				if($srcX >= 0 && $srcX < $srcw && $srcY >= 0 && $srcY < $srch) {
					$color = imagecolorat($srcImg, $srcX, $srcY );
				} else {
					$color = $bgcolor;
				}
				imagesetpixel($destimg, $x-$minX, $y-$minY, $color);
			}
		}
		return new Imager( $destimg, $this->getTransparencyInfo() );
	}

	function watermark( $img, $direction ) {
		if ( ! ($img instanceof Imager) ) $img = new Imager( $img );
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopyresampled($t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
		$wmark_width  = $img->width;
		$wmark_height = $img->height;
		
		$ti = $img->getTransparencyInfo();
		$alpharesize = false;
		if ( $ti != null && $ti->transparent && $ti->alphachannel ) {
			$alpharesize = true;
		}
		switch( $direction ) {
			case Imager::CENTER :
				if ( $alpharesize ) {
					imagecopy( $t, $img->getResource(), ( $this->width - $wmark_width ) / 2, ( $this->height - $wmark_height ) / 2, 0, 0, $wmark_width, $wmark_height );
				} else {
					imagecopymerge( $t, $img->getResource(), ( $this->width - $wmark_width ) / 2, ( $this->height - $wmark_height ) / 2, 0, 0, $wmark_width, $wmark_height, 100 );
				}
				break;
			case Imager::TOP_LEFT :
				if ( $alpharesize ) {
					imagecopy( $t, $img->getResource(), 0, 0, 0, 0, $wmark_width, $wmark_height );
				} else {
					imagecopymerge( $t, $img->getResource(), 0, 0, 0, 0, $wmark_width, $wmark_height, 100 );
				}
				break;
			case Imager::TOP_RIGHT :
				if ( $alpharesize ) {
					imagecopy( $t, $img->getResource(), $this->width - $wmark_width, 0, 0, 0, $wmark_width, $wmark_height );
				} else {
					imagecopymerge( $t, $img->getResource(), $this->width - $wmark_width, 0, 0, 0, $wmark_width, $wmark_height, 100 );
				}
				break;
			case Imager::BOTTOM_LEFT :
				if ( $alpharesize ) {
					imagecopy( $t, $img->getResource(), 0, $this->height - $wmark_height, 0, 0, $wmark_width, $wmark_height );
				} else {
					imagecopymerge( $t, $img->getResource(), 0, $this->height - $wmark_height, 0, 0, $wmark_width, $wmark_height, 100 );
				}
				break;
			default:
			case Imager::BOTTOM_RIGHT :
				if ( $alpharesize ) {
					imagecopy( $t, $img->getResource(), $this->width - $wmark_width, $this->height - $wmark_height, 0, 0, $wmark_width, $wmark_height );
				} else {
					imagecopymerge( $t, $img->getResource(), $this->width - $wmark_width, $this->height - $wmark_height, 0, 0, $wmark_width, $wmark_height, 100 );
				}
				break;
		}
		return new Imager( $t, $this->getTransparencyInfo() );
	}
	
	function darkness( $amount = 40 ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		for( $y=0; $y< $this->height; $y++ ) {
			for( $x=0; $x< $this->width; $x++ ) {
				$rgb = imagecolorat( $t, $x, $y );
				$r = ( $rgb >> 16 ) & 0xFF;
				$g = ( $rgb >> 8 ) & 0xFF;
				$b = $rgb & 0xFF;
				$nr = min( 255, max( $r - $r * $amount / 255, 0 ) );
				$ng = min( 255, max( $g - $g * $amount / 255, 0 ) );
				$nb = min( 255, max( $blue-$blue*$amount / 255, 0 ) );
				$ncolor = imagecolorallocate( $t, $nr, $ng, $nb );
				imagesetpixel( $t, $x, $y, $ncolor );
			}
		}
		return new Imager( $t, $this->getTransparencyInfo() );
	}
	
	/* Some imagefiler effects */
	function blur() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_SELECTIVE_BLUR );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function blurgaussian() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_GAUSSIAN_BLUR );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function brightness( $level = 10 ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_BRIGHTNESS, $level );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function contrast( $level = 10 ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_CONTRAST, $level );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function gamma( $from = 1.0, $to = 1.537 ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagegammacorrect( $t, $from, $to );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function grayscale() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_GRAYSCALE );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function negate() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_NEGATE );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function sepia() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_GRAYSCALE );
		imagefilter( $t, IMG_FILTER_COLORIZE, 112, 66, 20 );
		return new Imager( $t, $this->getTransparencyInfo() );
	}
	
	function sketch() {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_MEAN_REMOVAL );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function smooth( $level = 10 ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imagefilter( $t, IMG_FILTER_SMOOTH, $level );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function blurgaussian2() {
		$matrix = array(
			array(  1,  2,  1 ),
			array(  2,  4,  2 ),
			array(  1,  2,  1 )
		);
		$divisor = 16;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function emboss() {
		$matrix = array(
			array(  2,  0,  0 ),
			array(  0, -1,  0 ),
			array(  0,  0, -1 )
		);
		$divisor = 1;
		$offset = 127;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function edgeTopDown() {
		$matrix = array(
			array(  1,  1,  1 ),
			array(  1, -2,  1 ),
			array( -1, -1, -1 )
		);
		$divisor = 1;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function edgeEnhance() {
		$matrix = array(
			array(  0, -1,  0 ),
			array( -1,  5, -1 ),
			array(  0, -1,  0 )
		);
		$divisor = 1;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function hipass() {
		$matrix = array(
			array( -1, -1, -1 ),
			array( -1,  9, -1 ),
			array( -1, -1, -1 )
		);
		$divisor = 1;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function laplace() {
		$matrix = array(
			array( -1, -1, -1 ),
			array( -1,  8, -1 ),
			array( -1, -1, -1 )
		);
		$divisor = 1;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}
	
	function sharpen() {
		$matrix = array(
			array( -1, -1, -1 ),
			array( -1, 16, -1 ),
			array( -1, -1, -1 )
		);
		$divisor = 8;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function soften() {
		$matrix = array(
			array(  2,  2,  2 ),
			array(  2,  0,  2 ),
			array(  2,  2,  2 )
		);
		$divisor = 16;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function softenLess() {
		$matrix = array(
			array(  0,  1,  0 ),
			array(  1,  2,  1 ),
			array(  0,  1,  0 )
		);
		$divisor = 6;
		$offset = 0;
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}

	function convolution( array $matrix, $divisor, $offset ) {
		$t = imagecreatetruecolor( $this->width, $this->height );
		imagecopy( $t, $this->imgres, 0, 0, 0, 0, $this->width, $this->height );
		imageconvolution( $t, $matrix, $divisor, $offset );
		return new Imager( $t, $this->getTransparencyInfo() );
	}
}
?>
Return current item: Imager