PHP Classes

File: engine/class.www-imager.php

Recommend this page to a friend!
  Classes of Kristo Vaher  >  Wave Framework  >  engine/class.www-imager.php  >  Download  
File: engine/class.www-imager.php
Role: Class source
Content type: text/plain
Description: Imager Class
Class: Wave Framework
MVC framework for building Web sites and APIs
Author: By
Last change: Updated jQuery 1.10.0 and 2.0.1. Added better API versioning support that also takes into account overrides folders. Refactoring of Imager class to reduce duplicate code between Image Handler and Imager. Also fixed the bug introduced in 3.6.2 that generated incorrect image sprite sizes in dynamic image loading. Code review and some minor changes.
Date: 8 years ago
Size: 41,737 bytes
 

Contents

Class file image Download
<?php

/**
 * Wave Framework <http://www.waveframework.com>
 * Imager Class
 *
 * Imager is a class that acts as a wrapper to PHP GD library and has a number of methods to 
 * resize images with different resize algorithms as well as apply filtering to images and deal 
 * with image conversions between different formats. It can load an image resource from server 
 * or a URL and either store the edited image in a filesystem or push it to output buffer.
 *
 * @package    Imager
 * @author     Kristo Vaher <kristo@waher.net>
 * @copyright  Copyright (c) 2012, Kristo Vaher
 * @license    GNU Lesser General Public License Version 3
 * @tutorial   /doc/pages/imager.htm
 * @since      1.0.0
 * @version    3.6.4
 */

class WWW_Imager {

	/**
	 * This variable holds the image resource that Imager class handles during its operation.
	 */
	public $resource=false;
	
	/**
	 * This variable holds currently known image width in pixels.
	 */
	public $width=0;
	
	/**
	 * This variable holds currently known image height in pixels.
	 */
	public $height=0;

	/**
	 * Current image IMAGETYPE_X type value.
	 */
	public $type=false;
	
	/** 
	 * This method is used to load an image resource for the Imager class. $location should 
	 * be a file location in the system a web URL. This method automatically detects the type 
	 * of image as well as image resolution, which is stored in $width and $height variables.
	 * Method returns true if image was loaded successfully.
	 *
	 * @param string $location source file location in file system
	 * @return boolean
	 */
	public function input($location){
	
		// This functionality only works if GD library is loaded
		if(extension_loaded('gd')){
	
			// Checking if file actually exists in file system
			if($imageInfo=getimagesize($location)){

				// Assigning image parameters to object
				$this->width=$imageInfo[0];
				$this->height=$imageInfo[1];
				$this->type=$imageInfo[2];

				// Creating image resource object based on file type
				switch($this->type){
					case IMAGETYPE_JPEG:
						// Image is created from assumed JPEG file
						if(!$this->resource=imagecreatefromjpeg($location)){
							return false;
						}
						break;
					case IMAGETYPE_PNG:
						// Image is created from assumed PNG file
						if(!$this->resource=imagecreatefrompng($location)){
							return false;
						}
						// This saves the alpha settings of the image
						imagealphablending($this->resource,false);
						imagesavealpha($this->resource,true);
						break;
					case IMAGETYPE_GIF:
						// Image is created from assumed GIF file
						if(!$this->resource=imagecreatefromgif($location)){
							return false;
						}
						break;
					default:
						trigger_error('File format not supported',E_USER_ERROR);
						break;
				}
			
				// Image has been loaded
				return true;
				
			} else {
				// File was not found
				return false;
			}
			
		} else {
			// GD library is not enabled
			return false;
		}
		
	}
	
	/**
	 * This method stores the image in filesystem in $location folder and filename. If $location 
	 * is not set, then image is returned to output buffer. $quality is used for the compression 
	 * quality (from 0-100) and $format is used to define what file format the picture is 
	 * returned. $format can be 'jpg', 'png' or 'gif'.
	 *
	 * @param boolean|string $location new file location in file system. If not set, then returns file data to output
	 * @param integer $quality quality percentage, higher is better
	 * @param boolean|string $format output file extension or type, 'png', 'jpg' or 'gif'
	 * @return boolean
	 */
	public function output($location=false,$quality=90,$format=false){
	
		// Making sure quality is between acceptable values
		if($quality<0 || $quality>100){ 
			// 90 is a good high quality value for image compression
			$quality=90; 
		}
	
		// If output format is not set, then system uses format based on IMAGETYPE_XXX value
		if(!$format){
			switch($this->type){
				case IMAGETYPE_JPEG:
					$format='jpg';
					break;
				case IMAGETYPE_PNG:
					$format='png';
					break;
				case IMAGETYPE_GIF:
					$format='gif';
					break;
			}
		}
		
		// It output location is set, then file is stored in filesystem. If not set, then output is sent to user agent.
		if($location){
			// Different file types have different compression levels for quality
			switch($format){
				case 'jpg':
					return imagejpeg($this->resource,$location,$quality);
					break;
				case 'png':
					return imagepng($this->resource,$location,(9-floor($quality/10)));
					break;
				case 'gif':
					return imagegif($this->resource,$location);
					break;
				default:
					trigger_error('This output format is not supported',E_USER_ERROR);
					break;
			}
		} else {
			// Different file types have different compression levels for quality
			switch($format){
				case 'jpg':
                    // Pushing proper headers
                    header('Content-Type: image/jpeg');
					// Second parameter of null means that image is pushed to output buffer instead of stored in file
					if(imagejpeg($this->resource,null,$quality)){
						return true;
					} else {
						// 500 header is returned if file was not created
						header('HTTP/1.1 500 Internal Server Error');
						return false;
					}
					break;
				case 'png':
                    // Pushing proper headers
                    header('Content-Type: image/png');
					// PNG format has compression from 0-9 with 0 being the best, so quality is updated accordingly
					if(imagepng($this->resource,null,(9-floor($quality/10)))){
						return true;
					} else {
						// 500 header is returned if file was not created
						header('HTTP/1.1 500 Internal Server Error');
						return false;
					}
					break;
				case 'gif':
                    // Pushing proper headers
                    header('Content-Type: image/gif');
					// Second parameter not used means that image is pushed to output buffer instead of stored in file
					if(imagegif($this->resource)){
						return true;
					} else {
						// 500 header is returned if file was not created
						header('HTTP/1.1 500 Internal Server Error');
						return false;
					}
					break;
				default:
					trigger_error('This output format is not supported',E_USER_ERROR);
					break;
			}
		}

        // Something must have gone wrong
        return false;
		
	}
	
	/**
	 * This method parses parameter array and returns an array that can be used for image 
	 * manipulation in applyParameters() method. This method returns an array or a false 
	 * result in case the parameters were incorrect. $parameters is an array that is simlar 
	 * to Wave Framework dynamic image loading parameter string, except exploded to & character.
	 * 
	 * @param array $parameters array of parameters to be parsed
	 * @return mixed
	 */
	public function parseParameters($parameters){
		
		// These are the default settings
		// This array will be returned after parsing all of the parameters
		$settings=array(
			'width'=>$this->width,
			'height'=>$this->height,
			'algorithm'=>'fitcrop',
			'alpha'=>true,
			'red'=>0,
			'green'=>0,
			'blue'=>0,
			'top'=>'center',
			'left'=>'center',
			'quality'=>90,
			'filters'=>array(),
			'format'=>false
		);
		
		// Looping over the data bits to find additional parameters
		foreach($parameters as $parameter){
			switch($parameter){
				case 'fitcrop':
					// This is a resize algorithm flag
					$settings['algorithm']='fitcrop';
					break;
				case 'crop':
					// This is a resize algorithm flag
					$settings['algorithm']='crop';
					break;
				case 'fitwithbackground':
					// This is a resize algorithm flag
					$settings['algorithm']='fitwithbackground';
					break;
				case 'fitwithoutbackground':
					// This is a resize algorithm flag
					$settings['algorithm']='fitwithoutbackground';
					break;
				case 'widthonly':
					// This is a resize algorithm flag
					$settings['algorithm']='widthonly';
					break;
				case 'heightonly':
					// This is a resize algorithm flag
					$settings['algorithm']='heightonly';
					break;
				case 'jpg':
					// This is a file format flag
					$settings['format']='jpg';
					break;
				case 'png':
					// This is a file format flag
					$settings['format']='png';
					break;
				default:
					// If any of the resize algorithm and cache flags were not hit, the parameter is matched for other conditions
					if(strpos($parameter,'filter(')!==false){
					
						// Background color setting is assumed if rgb is present
						$filterSettings=str_replace(array('filter(',')'),'',$parameter);
						$filterSettings=explode(',',$filterSettings);
						
						// Storing data of new filter
						$filter=array();
						// First number is the filter type
						if($filterSettings[0]!=''){
							// Filter type can also have parameters
							$typeSettings=explode('@',$filterSettings[0]);
							// First parameter is the filter type
							$filter['type']=$typeSettings[0];
							// It is possible to 'layer' the effect by defining alpha level as the second parameter
							if(isset($typeSettings[1])){
								$filter['alpha']=$typeSettings[1];
							} else {
								// Filter effect is 100% if alpha was not defined
								$filter['alpha']=100;
							}
						}
						
						// Storing data of new filters settings
						$filter['settings']=array();
						// Storing other filter variables
						for($i=1;isset($filterSettings[$i]);$i++){
							$filter['settings'][]=$filterSettings[$i];
						}
						
						// Adding filter to list of filters
						$settings['filters'][]=$filter;
						
					} elseif(strpos($parameter,'rgb(')!==false){
					
						// This tells Imager that alpha channel won't be used since RGB is set
						$settings['alpha']=false;
					
						// Background color setting is assumed if rgb is present
						$colors=str_replace(array('rgb(',')'),'',$parameter);
						$colors=explode(',',$colors);
						// First number in parameter is red color amount
						if($colors[0]!=''){
							$settings['red']=$colors[0];
						}
						// Second number in parameter is green color amount
						if(isset($colors[1]) && $colors[1]!=''){
							$settings['green']=$colors[1];
						}
						// Third number in parameter is blue color amount
						if(isset($colors[2]) && $colors[2]!=''){
							$settings['blue']=$colors[2];
						}
						
					} elseif(strpos($parameter,'-')!==false){
					
						// Position setting is assumed if dash is present
						$positions=explode('-',$parameter);
						// First value is top position
						// This can be 'top', 'center', 'bottom' or a number in pixels
						// It can also include the size of the sprite set on the canvas
						if($positions[0]!=''){
							$settings['top']=$positions[0];
						}
						// Second value is left position
						// This can be 'left', 'center', 'right' or a number in pixels
						// It can also include the size of the sprite set on the canvas
						if($positions[1]!=''){
							$settings['left']=$positions[1];
						}
						
					} elseif(strpos($parameter,'@')!==false){
					
						// Quality setting is assumed if @ sign is present
						$settings['quality']=str_replace('@','',$parameter);
						
					} elseif(strpos($parameter,'x')!==false){
					
						// It is assumed that the remaining parameter is for image dimensions
						$dimensions=explode('x',$parameter);
						// First number is width
						if($dimensions[0]!=''){
							$settings['width']=$dimensions[0];
						}
						// Second number, if defined, is height
						if(isset($dimensions[1]) && $dimensions[1]!=''){
							$settings['height']=$dimensions[1];
						} else {
							// If height is not defined then height is considered to be as long as width
							$settings['height']=$settings['width'];
						}
						
					} else {
					
						// An incorrect parameter was sent
						return false;
			
					}
					break;
			}
		}
		
		// Returning the parsed parameters
		return $settings;
	
	}
	
	/**
	 * This method applies series of parameters to the currently loaded image file.
	 * These parameters are either parsed through parseParameters() method or manually 
	 * sent to the function. This is the list of parameters expected by the function:
	 *  'width' - Width of the resulting image
	 *  'height' - Height of the resulting image
	 *  'algorithm' - Algorithm used for the image resize (fitcrop,crop,fitwithbackground,fitwithoutbackground,widthonly,heightonly)
	 *  'alpha' - Whether alpha map is used, if possible, for background
	 *  'red' - 0-255 value for red color for background
	 *  'green' - 0-255 value for green color for background
	 *  'blue' - 0-255 value for blue color for background
	 *  'top' - Sprite position on canvas (top, bottom, center or pixel value)
	 *  'left' - Sprite position on canvas (left, right, center or pixel value)
	 *  'filters' - Array of filter data
	 *
	 * @param array $parameters an array of parameters that are applied to the image
	 * @return boolean
	 */
	public function applyParameters($parameters){
		
		// If algorithm is set
		if(isset($parameters['algorithm'])){
		
			// Image is filtered through resize algorithm and saved in cache directory
			switch($parameters['algorithm']){
				case 'fitcrop':
					// Crop algorithm fits the image into set dimensions, cutting the edges that do not fit
					if(!$this->resizeFitCrop($parameters['width'],$parameters['height'],$parameters['left'],$parameters['top'])){
						trigger_error('Cannot resize image with fit-crop algorithm',E_USER_ERROR);
					}
					break;
				case 'crop':
					// Crop algorithm places image in new dimensions box cutting the edges that do not fit
					if(!$this->resizeCrop($parameters['width'],$parameters['height'],$parameters['left'],$parameters['top'],$parameters['red'],$parameters['green'],$parameters['blue'],$parameters['alpha'])){
						trigger_error('Cannot resize image with crop algorithm',E_USER_ERROR);
					}
					break;
				case 'fitwithbackground':
					// This fits image inside the box and gives it certain color background (if applicable)
					if(!$this->resizeFit($parameters['width'],$parameters['height'],$parameters['left'],$parameters['top'],$parameters['red'],$parameters['green'],$parameters['blue'],$parameters['alpha'])){
						trigger_error('Cannot resize image with fit-with-background algorithm',E_USER_ERROR);
					}
					break;
				case 'fitwithoutbackground':
					// This simply resizes the image to fit specific dimensions
					if(!$this->resizeFitNoBackground($parameters['width'],$parameters['height'])){
						trigger_error('Cannot resize image with fit-without-background algorithm',E_USER_ERROR);
					}
					break;
				case 'widthonly':
					// This resizes the image to fixed width
					if(!$this->resizeWidth($parameters['width'])){
						trigger_error('Cannot resize image with width-only algorithm',E_USER_ERROR);
					}
					break;
				case 'heightonly':
					// This resizes the image to fixed height
					if(!$this->resizeHeight($parameters['height'])){
						trigger_error('Cannot resize image with height-only algorithm',E_USER_ERROR);
					}
					break;
			}
		
			// As long as there are set filters
			if(!empty($parameters['filters'])){
				// Each filter is applied, one by one
				foreach($parameters['filters'] as $filter){
					if(!$this->applyFilter($filter['type'],$filter['alpha'],$filter['settings'])){
						trigger_error('Cannot apply filter '.$filter['type'],E_USER_ERROR);
					}
				}
			}
		
		} else {
		
			// Some of the parameters were missing
			return false;
			
		}
				
		// Processing is complete
		return true;
		
	}
	
	/**
	 * This is a resize-algorithm method that resizes the current image resource to $width and 
	 * $height. This resize method crops the image by removing the parts of picture that are left 
	 * out of $width and $height dimensions. Variables $left and $top can be used to set the 
	 * position of the image on the new, resized canvas and accept both numeric (pixel) values 
	 * as well as relative ones, such as 'center', 'left', 'right' and 'top, 'bottom'. Position 
	 * values can also include a percentage for stretching the image in either direction by 
	 * writing percentage after * symbol.
	 *
	 * @param integer $width width of resulting image
	 * @param integer $height height of resulting image
	 * @param string $left position from the left edge,an be 'center', 'left', 'right' or a pixel value.
	 * @param string $top position from the top edge,an be 'center', 'top', 'bottom' or a pixel value.
	 * @return boolean
	 */
	public function resizeFitCrop($width,$height,$left='center',$top='center'){
	
		// Canceling function if resizing is not needed
		if($this->width==$width && $this->height==$height){
			return true;
		}
	
		// System resizes source image based on which side of the image would be left 'outside' of the frame
		if(($this->height/$height)<($this->width/$width)){
			if(!$this->resizeHeight($height)){
				return false;
			}
		} else {
			if(!$this->resizeWidth($width)){
				return false;
			}
		}
		
		// Finding out fixed image size or percentages
		$leftFixed=true;
		$left=explode(',',$left);
		if(!isset($left[1])){
			$leftFixed=false;
			// Percentages are defined by * symbol
			$left=explode('*',$left[0]);
			if(!isset($left[1])){
				$left[1]=100;
			}
		}
		
		// Left position is calculated, if value is a string instead of a number
		switch($left[0]){
			case 'center':
				// Calculating image left position based on positioning difference with new dimensions
				$left[0]=-(round(($this->width-$width)/2));
				break;
			case 'left':
				// Left positioning is always 0
				$left[0]=0;
				break;
			case 'right':
				// Right position is simply the current image width subtracted from new width
				$left[0]=$width-$this->width;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the left value is not numeric
				if(!is_numeric($left[0])){
					trigger_error('This left position ('.$left[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Finding out fixed sprite size or percentages for size
		$topFixed=true;
		$top=explode(',',$top);
		if(!isset($top[1])){
			$topFixed=false;
			// Percentages are defined by * symbol
			$top=explode('*',$top[0]);
			if(!isset($top[1])){
				$top[1]=100;
			}
		}
		
		// Top position is calculated, if value is a string instead of a number
		switch($top[0]){
			case 'center':
				// Calculating image top position based on positioning difference with new dimensions
				$top[0]=-(round(($this->height-$height)/2));
				break;
			case 'top':
				// Top positioning is always 0
				$top[0]=0;
				break;
			case 'bottom':
				// Top position is simply the current image height subtracted from new height
				$top[0]=$height-$this->height;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the top value is not numeric
				if(!is_numeric($top[0])){
					trigger_error('This top position ('.$top[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Temporary image is created for the output
		$tmpImage=imagecreatetruecolor($width,$height);
		// This preserves alpha maps, if it exists (such as for PNG)
		imagealphablending($tmpImage,false);
		imagesavealpha($tmpImage,true);
		// Current image resource is placed on temporary resource
		imagecopyresampled($tmpImage,$this->resource,$left[0],$top[0],0,0,(($leftFixed)?$left[1]:round($left[1]/100*$this->width)),(($topFixed)?$top[1]:round($top[1]/100*$this->height)),$this->width,$this->height);
		
		// New dimensions and temporary image resource is assigned as resource of this object
		$this->width=$width;
		$this->height=$height;
		$this->resource=$tmpImage;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This is a resize-algorithm method that resizes the current image resource to $width 
	 * and $height without resizing the actual image. This resize method crops the image by 
	 * removing the parts of picture that are left out of $width and $height dimensions. 
	 * Variables $left and $top can be used to set the position of the image on the new, 
	 * resized canvas and accept both numeric (pixel) values as well as relative ones, such 
	 * as 'center', 'left', 'right' and 'top, 'bottom'. Position values can also include a 
	 * percentage for stretching the image in either direction by writing percentage 
	 * after * symbol. $red, $green and $blue are RGB values for background color in case 
	 * background is required.
	 *
	 * @param integer $width width of resulting image
	 * @param integer $height height of resulting image
	 * @param string $left position from the left edge, can be 'center', 'left', 'right' or a pixel value
	 * @param string $top position from the top edge, can be 'center', 'top', 'bottom' or a pixel value
	 * @param integer $red amount of red color for background, from 0-255
	 * @param integer $green amount of green color for background, from 0-255
	 * @param integer $blue amount of blue color for background, from 0-255
	 * @param boolean $alpha if alpha channel is used for PNG pictures
	 * @return boolean
	 */
	public function resizeCrop($width,$height,$left='center',$top='center',$red=0,$green=0,$blue=0,$alpha=true){
	
		// Canceling function if resizing is not needed
		if($this->width==$width && $this->height==$height){
			return true;
		}
		
		// PNG images do not require a background
		if($this->type!=IMAGETYPE_PNG){
			// If red color is out of allowed range it is defaulted to 0
			if($red<0 || $red>255){ 
				$red=0; 
			}
			// If green color is out of allowed range it is defaulted to 0
			if($green<0 || $green>255){ 
				$green=0; 
			}
			// If blue color is out of allowed range it is defaulted to 0
			if($blue<0 || $blue>255){ 
				$blue=0; 
			}
		}
	
		// Finding out fixed image size or percentages
		$leftFixed=true;
		$left=explode(',',$left);
		if(!isset($left[1])){
			$leftFixed=false;
			// Percentages are defined by * symbol
			$left=explode('*',$left[0]);
			if(!isset($left[1])){
				$left[1]=100;
			}
		}
		
		// Left position is calculated, if value is a string instead of a number
		switch($left[0]){
			case 'center':
				// Calculating image left position based on positioning difference with new dimensions
				$left[0]=-(round(($this->width-$width)/2));
				break;
			case 'left':
				// Left positioning is always 0
				$left[0]=0;
				break;
			case 'right':
				// Right position is simply the current image width subtracted from new width
				$left[0]=$width-$this->width;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the left value is not numeric
				if(!is_numeric($left[0])){
					trigger_error('This left position ('.$left[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Finding out fixed sprite size or percentages for size
		$topFixed=true;
		$top=explode(',',$top);
		if(!isset($top[1])){
			$topFixed=false;
			// Percentages are defined by * symbol
			$top=explode('*',$top[0]);
			if(!isset($top[1])){
				$top[1]=100;
			}
		}
		
		// Top position is calculated, if value is a string instead of a number
		switch($top[0]){
			case 'center':
				// Calculating image top position based on positioning difference with new dimensions
				$top[0]=-(round(($this->height-$height)/2));
				break;
			case 'top':
				// Top positioning is always 0
				$top[0]=0;
				break;
			case 'bottom':
				// Top position is simply the current image height subtracted from new height
				$top[0]=$height-$this->height;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the top value is not numeric
				if(!is_numeric($top[0])){
					trigger_error('This top position ('.$top[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Temporary image is created for the output		
		$tmpImage=imagecreatetruecolor($width,$height);
		
		// Background color is transparent for PNG images
		if($this->type!=IMAGETYPE_PNG){
			// Since the image might have a background color, the temporary image is filled with background color
			imagefill($tmpImage,0,0,imagecolorallocate($tmpImage,$red,$green,$blue));
		} elseif(!$alpha){
			// PNG images are filled with alpha background color
			imagefill($tmpImage,0,0,imagecolorallocatealpha($tmpImage,$red,$green,$blue,0));
			// This preserves alpha maps, if it exists (such as for PNG)
			imagealphablending($tmpImage,true);
			// Saving the alpha map
			imagesavealpha($tmpImage,true);
		} else {
			// PNG images are filled with alpha background color
			imagefill($tmpImage,0,0,imagecolorallocatealpha($tmpImage,0,0,0,127));
			// This preserves alpha maps, if it exists (such as for PNG)
			imagealphablending($tmpImage,false);
			// Saving the alpha map
			imagesavealpha($tmpImage,true);
		}
		
		// Current image resource is placed on temporary resource
		imagecopyresampled($tmpImage,$this->resource,$left[0],$top[0],0,0,(($leftFixed)?$left[1]:round($left[1]/100*$this->width)),(($topFixed)?$top[1]:round($top[1]/100*$this->height)),$this->width,$this->height);
		
		// New dimensions and temporary image resource is assigned as resource of this object
		$this->width=$width;
		$this->height=$height;
		$this->resource=$tmpImage;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This is a resize-algorithm method that resizes the current image simply by resizing the 
	 * image to $width and $height and leaves the remaining space for background color. This 
	 * resize method crops the image by removing the parts of picture that are left out of $width 
	 * and $height dimensions. Variables $left and $top can be used to set the position of the 
	 * image on the new, resized canvas and accept both numeric (pixel) values as well as relative 
	 * ones, such as 'center', 'left', 'right' and 'top, 'bottom'. Position values can also include 
	 * a percentage for stretching the image in either direction by writing percentage after * symbol.
	 * $red, $green and $blue are RGB values for background color in case background is required.
	 * 
	 * @param integer $width width of resulting image
	 * @param integer $height height of resulting image
	 * @param string|integer $left position from the left edge. Can be 'center', 'left', 'right' or a pixel value
	 * @param string|integer $top position from the top edge. Can be 'center', 'top', 'bottom' or a pixel value
	 * @param integer $red amount of red color for background, from 0-255
	 * @param integer $green amount of green color for background, from 0-255
	 * @param integer $blue amount of blue color for background, from 0-255
	 * @param boolean $alpha if alpha channel is used for PNG pictures
	 * @return boolean
	 */
	public function resizeFit($width,$height,$left='center',$top='center',$red=0,$green=0,$blue=0,$alpha=true){
	
		// Canceling function if resizing is not needed
		if($this->width==$width && $this->height==$height){
			return true;
		}
	
		// PNG images do not require a background
		if($this->type!=IMAGETYPE_PNG){
			// If red color is out of allowed range it is defaulted to 0
			if($red<0 || $red>255){ 
				$red=0; 
			}
			// If green color is out of allowed range it is defaulted to 0
			if($green<0 || $green>255){ 
				$green=0; 
			}
			// If blue color is out of allowed range it is defaulted to 0
			if($blue<0 || $blue>255){ 
				$blue=0; 
			}
		}
	
		// System resizes source image based on which side of the image would be left 'outside' of the frame		
		if(($this->height/$height)>($this->width/$width)){
			if(!$this->resizeHeight($height)){
				return false;
			}
		} else {
			if(!$this->resizeWidth($width)){
				return false;
			}
		}
		
		// Finding out fixed image size or percentages
		$leftFixed=true;
		$left=explode(',',$left);
		if(!isset($left[1])){
			$leftFixed=false;
			// Percentages are defined by * symbol
			$left=explode('*',$left[0]);
			if(!isset($left[1])){
				$left[1]=100;
			}
		}
		
		// Left position is calculated, if value is a string instead of a number
		switch($left[0]){
			case 'center':
				// Calculating image left position based on positioning difference with new dimensions
				$left[0]=-(round(($this->width-$width)/2));
				break;
			case 'left':
				// Left positioning is always 0
				$left[0]=0;
				break;
			case 'right':
				// Right position is simply the current image width subtracted from new width
				$left[0]=$width-$this->width;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the left value is not numeric
				if(!is_numeric($left[0])){
					trigger_error('This left position ('.$left[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Finding out fixed sprite size or percentages for size
		$topFixed=true;
		$top=explode(',',$top);
		if(!isset($top[1])){
			$topFixed=false;
			// Percentages are defined by * symbol
			$top=explode('*',$top[0]);
			if(!isset($top[1])){
				$top[1]=100;
			}
		}
		
		// Top position is calculated, if value is a string instead of a number
		switch($top[0]){
			case 'center':
				// Calculating image top position based on positioning difference with new dimensions
				$top[0]=-(round(($this->height-$height)/2));
				break;
			case 'top':
				// Top positioning is always 0
				$top[0]=0;
				break;
			case 'bottom':
				// Top position is simply the current image height subtracted from new height
				$top[0]=$height-$this->height;
				break;
			default:
				// Numeric positioning is possible, but error is thrown when the top value is not numeric
				if(!is_numeric($top[0])){
					trigger_error('This top position ('.$top[0].') is not supported',E_USER_ERROR);
				}
				break;
		}
		
		// Temporary image is created for the output
		$tmpImage=imagecreatetruecolor($width,$height);
		
		// Background color is transparent for PNG images
		if($this->type!=IMAGETYPE_PNG){
			// Since the image might have a background color, the temporary image is filled with background color
			imagefill($tmpImage,0,0,imagecolorallocate($tmpImage,$red,$green,$blue));
		} elseif(!$alpha){
			// PNG images are filled with alpha background color
			imagefill($tmpImage,0,0,imagecolorallocatealpha($tmpImage,$red,$green,$blue,0));
			// This preserves alpha maps, if it exists (such as for PNG)
			imagealphablending($tmpImage,true);
			// Saving the alpha map
			imagesavealpha($tmpImage,true);
		} else {
			// PNG images are filled with alpha background color
			imagefill($tmpImage,0,0,imagecolorallocatealpha($tmpImage,0,0,0,127));
			// This preserves alpha maps, if it exists (such as for PNG)
			imagealphablending($tmpImage,false);
			// Saving the alpha map
			imagesavealpha($tmpImage,true);
		}
		
		// Current image resource is placed on temporary resource
		imagecopyresampled($tmpImage,$this->resource,$left[0],$top[0],0,0,(($leftFixed)?$left[1]:round($left[1]/100*$this->width)),(($topFixed)?$top[1]:round($top[1]/100*$this->height)),$this->width,$this->height);
		
		// New dimensions and temporary image resource is assigned as resource of this object
		$this->width=$width;
		$this->height=$height;
		$this->resource=$tmpImage;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This is a resize-algorithm method that resizes the current image simply by resizing the 
	 * image to $width and $height and removing the dimensions that would otherwise be left for 
	 * a background.
	 *
	 * @param integer $width width of resulting image
	 * @param integer $height height of resulting image
	 * @return boolean
	 */
	public function resizeFitNoBackground($width,$height){
	
		// Canceling function if resizing is not needed
		if($this->width==$width && $this->height==$height){
			return true;
		}
	
		// System resizes source image based on which side of the image would be left 'outside' of the frame
		if(($this->height/$height)>($this->width/$width)){
			if(!$this->resizeHeight($height)){
				return false;
			}
		} else {
			if(!$this->resizeWidth($width)){
				return false;
			}
		}
		
		// New dimensions are assigned for this object
		$this->width=$width;
		$this->height=$height;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This method simply resizes the image to fixed width set with $width variable. New image 
	 * height depends on the result of the resize.
	 *
	 * @param integer $width width of resulting image
	 * @return boolean
	 */
	public function resizeWidth($width){
	
		// Canceling function if resizing is not needed
		if($this->width==$width){
			return true;
		}
	
		// Ratio is used to calculate the ratio which is used to resize the image
		$ratio=$this->width/$width;
		// New height is calculated according to ratio
		$height=round($this->height/$ratio);
		
		// Temporary image is created for the output
		$tmpImage=imagecreatetruecolor($width,$height);
		// This preserves alpha maps, if it exists (such as for PNG)
		imagealphablending($tmpImage,false);
		imagesavealpha($tmpImage,true);
		
		// Current image resource is placed on temporary resource
		if(!imagecopyresampled($tmpImage,$this->resource,0,0,0,0,$width,$height,$this->width,$this->height)){
			return false;
		}
		
		// New dimensions and temporary image resource is assigned as resource of this object
		$this->width=$width;
		$this->height=$height;
		$this->resource=$tmpImage;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This method simply resizes the image to fixed height set with $height variable. New image 
	 * width depends on the result of the resize.
	 *
	 * @param integer $height height of resulting image
	 * @return boolean
	 */
	public function resizeHeight($height){
	
		// Canceling function if resizing is not needed
		if($this->height==$height){
			return true;
		}
	
		// Ratio is used to calculate the ratio which is used to resize the image
		$ratio=$this->height/$height;
		// New width is calculated according to ratio
		$width=round($this->width/$ratio);
		
		// Temporary image is created for the output
		$tmpImage=imagecreatetruecolor($width,$height);
		// This preserves alpha maps, if it exists (such as for PNG)
		imagealphablending($tmpImage,false);
		imagesavealpha($tmpImage,true);
		
		// Current image resource is placed on temporary resource
		if(!imagecopyresampled($tmpImage,$this->resource,0,0,0,0,$width,$height,$this->width,$this->height)){
			return false;
		}
		
		// New dimensions and temporary image resource is assigned as resource of this object
		$this->width=$width;
		$this->height=$height;
		$this->resource=$tmpImage;
		
		// Image has been resized
		return true;
		
	}
	
	/**
	 * This method is a wrapper for imagefilter() and imageconvolution() methods. $type can be 
	 * 'negative', 'grayscale', 'brightness', 'contrast', 'colorize', 'alphacolorize', 'edge', 
	 * 'emboss', 'blur', 'soften', 'sketch', 'smooth', 'pixelate' and 'convulate'. $alpha is 
	 * the percentage that this filter effect will be applied to the original image as a layer. 
	 * $settings is an array of variables that are expected to be sent with imagefilter() and 
	 * imageconvulation() methods.
	 *
	 * @param integer $type filtering type
	 * @param integer $alpha level of alpha layering to use on top of original image
	 * @param array $settings filter settings is an array that carries up to three variables
	 * @return boolean
	 */
	public function applyFilter($type,$alpha=100,$settings=array()){
	
		// If alpha level is outside the permitted values
		if($alpha<0 || $alpha>100){ 
			$alpha=100; 
		}
		
		// Storing original type for reference
		$requestedType=$type;

        // Amount of settings/variables that are required
        $settingsRequired=0;
	
		// Type is basically a shortcut to imagefilter() function
		switch($type){
			case 'negative':
				// Reverses all colors of the image
				$type=IMG_FILTER_NEGATE;
				break;
			case 'grayscale':
				// Converts the image into grayscale
				$type=IMG_FILTER_GRAYSCALE;
				break;
			case 'brightness':
				// Changes the brightness of the image, first setting defines brightness level
				$type=IMG_FILTER_BRIGHTNESS;
				// Defines the amount of settings to use
				$settingsRequired=1;
				break;
			case 'contrast':
				// Changes the contrast of the image, first setting defines contrast strength
				$type=IMG_FILTER_CONTRAST;
				// Defines the amount of settings to use
				$settingsRequired=1;
				break;
			case 'colorize':
				// Like 'grayscale', except you can specify the color. Settings are 'red', 'green' and 'blue' and alpha
				$type=IMG_FILTER_COLORIZE;
				// Defines the amount of settings to use
				$settingsRequired=3;
				break;
			case 'alphacolorize':
				// Like 'grayscale', except you can specify the color. Settings are 'red', 'green' and 'blue' and alpha
				$type=IMG_FILTER_COLORIZE;
				// Defines the amount of settings to use
				$settingsRequired=4;
				break;
			case 'edge':
				// Uses edge detection to highlight the edges in the image.
				$type=IMG_FILTER_EDGEDETECT;
				break;
			case 'emboss':
				// Embosses the image
				$type=IMG_FILTER_EMBOSS;
				break;
			case 'blur':
				// Blurs the image using the Gaussian method
				$type=IMG_FILTER_GAUSSIAN_BLUR;
				break;
			case 'soften':
				// Softens the image
				$type=IMG_FILTER_SELECTIVE_BLUR;
				break;
			case 'sketch':
				// Uses mean removal to achieve a sketch effect
				$type=IMG_FILTER_MEAN_REMOVAL;
				break;
			case 'smooth':
				// Makes the image smoother, first setting defines the level of smoothness
				$type=IMG_FILTER_SMOOTH;
				// Defines the amount of settings to use
				$settingsRequired=1;
				break;
			case 'pixelate':
				// Applies pixelation effect to the image, setting 1 defines block size and setting 2 the effect mode
				$type=IMG_FILTER_PIXELATE;
				// Defines the amount of settings to use
				$settingsRequired=2;
				break;
			case 'convulate':
				// Applies pixelation effect to the image, setting 1 defines block size and setting 2 the effect mode
				$type='convulate';
				// Defines the amount of settings to use
				$settingsRequired=11;
				break;
			default:
				trigger_error($requestedType.' filter is not available',E_USER_ERROR);
				break;
		}
		
		// If incorrect number of settings are used then error is thrown
		if(count($settings)!=$settingsRequired){
			trigger_error('Incorrect amount of filter settings for '.$requestedType.', '.count($settings).' set but '.$settingsRequired.' required',E_USER_ERROR);
		}
		
		// If alpha setting is used, then the resulting image will be 'merged'
		if($alpha!=100){
			// Temporary image is created for the output
			$tmpImage=imagecreatetruecolor($this->width,$this->height);
			// This preserves alpha maps, if it exists (such as for PNG)
			imagealphablending($tmpImage,false);
			imagesavealpha($tmpImage,true);
			// Current image resource is placed on temporary resource
			if(!imagecopyresampled($tmpImage,$this->resource,0,0,0,0,$this->width,$this->height,$this->width,$this->height)){
				return false;
			}
		}
		
		// Convulation is a complicated function
		if($type=='convulate'){
			// Convulation matrix is 3x3 array of floats
			$matrix=array(array($settings[0],$settings[1],$settings[2]),array($settings[3],$settings[4],$settings[5]),array($settings[6],$settings[7],$settings[8]));
			// Convulation applied
			if(!imageconvolution($this->resource, $matrix, $settings[9], $settings[10])){
				return false;
			}
		} else {
			// This applies the requested filter
			// imagefilter() expects different amount of parameters, this takes all conditions into account
			switch (count($settings)){
				case 4:
					if(!imagefilter($this->resource,$type,$settings[0],$settings[1],$settings[2],$settings[3])){
						return false;
					}
					break;
				case 3:
					if(!imagefilter($this->resource,$type,$settings[0],$settings[1],$settings[2])){
						return false;
					}
					break;
				case 2:
					if(!imagefilter($this->resource,$type,$settings[0],$settings[1])){
						return false;
					}
					break;
				case 1:
					if(!imagefilter($this->resource,$type,$settings[0])){
						return false;
					}
					break;
				default:
					if(!imagefilter($this->resource,$type)){
						return false;
					}
					break;
			}
		}
		
		// Filtered image is layered on top of the original, if alpha is not 100%
		if($alpha!=100){
			// Alpha value in the end does the layering
			if(!imagecopymerge($tmpImage,$this->resource,0,0,0,0,$this->width,$this->height,$alpha)){
				return false;
			}
			// New image is set as the resource
			$this->resource=$tmpImage;
		}
		
		// Processing complete
		return true;
	
	}
  
}

?>
For more information send a message to info at phpclasses dot org.