Location: PHPKode > scripts > PHP Imagizer - Image Manipulator > PhpImagizer-ver1.0/PhpImagizer.php
<?php
/** 
 * @author Ruslan Glick
 * @version 1.0
 * @copyright (c) 2011 - Present, Ruslan Glick
 * 
 */
require_once 'PhpImagizerException.php';

class PhpImagizer
{
    /**
     * 
     * Source file name
     * @var string
     */
	private $_srcFileName;
    
	/**
	 * 
	 * Destination file name
	 * @var string
	 */
    private $_destFileName;
    
    /**
     * 
     * Image type
     * @var int
     */
    private $_type;
    
    /**
     * 
     * Image resource
     * @var resource
     */
    private $_imageResource;
    
    /**
     * 
     * Width of an image
     * @var int
     */
    private $_width;
    
    /**
     * 
     * Height of an image
     * @var int
     */
    private $_height;
    
    /**
     * Quality of an destination image
     * 
     * @var int
     */
    private $_quality = 100;
    
    /**
     * Watermark position: Center
     * @var int
     */
    const POSITION_CENTER = 1;
    
    /**
     * Watermark position: Top Center
     * @var int
     */
    const POSITION_TOP_CENTER = 2;
    
    /**
     * Watermark position: Top Left
     * @var int
     */
    const POSITION_TOP_LEFT = 3;
    
    /**
     * Watermark position: Top Right
     * @var int
     */
    const POSITION_TOP_RIGHT = 4;
    
    /**
     * Watermark position: Bottom Center
     * @var int
     */
    const POSITION_BOTTOM_CENTER = 5;
    
    /**
     * Watermark position: Bottom Left
     * @var int
     */
    const POSITION_BOTTOM_LEFT = 6;
    
    /**
     * Watermark position: Bottom Right
     * @var int
     */
    const POSITION_BOTTOM_RIGHT = 7;
    
    /**
     * Watermark margin
     * @var int
     */
    const MARGIN = 5;
    
    /**
     * 
     * Constructor
     * @param string $filename
     * @param string $destFileName
     */
	public function __construct($filename)
    {
    	// @todo: check if GD is loaded and which version
    	$this->setSrcFileName($filename);
    	$this->_load();
    }
    
    /**
     * Destructor
     */
    public function __destruct()
    {
    	if (is_resource($this->getImageResource())) {
    		imagedestroy($this->getImageResource());
    	}
    }
    
    /**
     * Resize the image horizontally or vertically and mainain aspect ratio
     * @param int $maxSize
     */
    public function fitSize($maxSize)
    {
    	if($this->getWidth() > $this->getHeight()){
			$this->byWidth($maxSize);
		} else {
			$this->byHeight($maxSize);
		}
    }
    
    /**
     * Resize the image horizontally and mainain aspect ratio
     * @param int $maxWidth
     */
    public function byWidth($maxWidth)
    {
    	$this->_load();
    	$width = $this->getWidth();
    	if($width > $maxWidth) {
			$scale = $width / $maxWidth;
			$newWidth = $width / $scale;
			$newHeight = $this->getHeight() / $scale;
			$this->_resize($newWidth, $newHeight);
		}
    }
    
    /**
     * Resize the image vertically and mainain aspect ratio
     * @param int $maxHeight
     */
	public function byHeight($maxHeight)
    {
    	$this->_load();
    	$height = $this->getHeight();
    	if($height > $maxHeight) {
			$scale = $height / $maxHeight;
			$newWidth = $this->getWidth() / $scale;
			$newHeight = $height / $scale;
			$this->_resize($newWidth, $newHeight);
    	}
    }
    
    /**
     * Crop image to $width x $height
     * @param int $width
     * @param int $height
     */
    public function crop($width, $height)
    {
    	$new_x = 0;
		$new_y = 0;
		$new_w = $this->getWidth();
		$new_h = $this->getHeight();

		$tmp_scl_x = $this->getWidth() / $width;
		$tmp_scl_y = $this->getHeight() / $height;

		if($tmp_scl_x > $tmp_scl_y) {
			$new_w = $this->getWidth() * $tmp_scl_y / $tmp_scl_x;
			$new_x = ($this->getWidth() - $new_w) / 2;
		}
		if($tmp_scl_x < $tmp_scl_y) {
			$new_h = $this->getHeight() * $tmp_scl_x / $tmp_scl_y;
			$new_y = ($this->getHeight() - $new_h) / 2;
		}
		$this->_crop($new_x, $new_y, $new_w, $new_h);
		$this->_resize($width, $height);
    }
    
    /**
     * Embed watermark image into image
     * 
     * First parameter is a image filename which will be embeded into image
     * Second parameter is a position, allowed parameters are: 
     * 	POSITION_TOP_LEFT
     *  POSITION_TOP_CENTER
     * 	POSITION_TOP_RIGHT
     * 	POSITION_CENTER
     * 	POSITION_BOTTOM_LEFT
     * 	POSITION_BOTTOM_CENTER
     * 	POSITION_BOTTOM_RIGHT
     * 
     * @param string $filename
     * @param int $position
     */
    public function watermarkImage($filename, $position=self::POSITION_CENTER)
    {
    	$watermark = new PhpImagizer($filename);
    	$watermark->_load();
    	switch ($position) {
    		case self::POSITION_TOP_LEFT:
    			$destX = self::MARGIN;
    			$destY = self::MARGIN;
    			break;
    		case self::POSITION_TOP_CENTER:
    			$destX = ceil($this->getWidth() / 2 - $watermark->getWidth() / 2);
    			$destY = self::MARGIN;
    			break;
    		case self::POSITION_TOP_RIGHT:
    			$destX = $this->getWidth() - $watermark->getWidth() - self::MARGIN;
    			$destY = self::MARGIN;
    			break;
    		case self::POSITION_CENTER:
			default:
    			$destX = ceil($this->getWidth() / 2 - $watermark->getWidth() / 2);
    			$destY = ceil($this->getHeight() / 2 - $watermark->getHeight() / 2);
    			break;
			case self::POSITION_BOTTOM_LEFT:
				$destX = self::MARGIN;
				$destY = $this->getHeight() - $watermark->getHeight() - self::MARGIN;
				break;
    		case self::POSITION_BOTTOM_CENTER:
    			$destX = ceil($this->getWidth() / 2 - $watermark->getWidth() / 2);
    			$destY = $this->getHeight() - $watermark->getHeight() - self::MARGIN;
    			break;
    		case self::POSITION_BOTTOM_RIGHT:
    			$destX = $this->getWidth() - $watermark->getWidth() - self::MARGIN;
    			$destY = $this->getHeight() - $watermark->getHeight() - self::MARGIN;
    			break;
    	}
    	    	
    	imagecopymerge ( $this->getImageResource(), $watermark->getImageResource(), $destX, $destY, 0, 0, $watermark->getWidth(), $watermark->getHeight(), 100);
    	imagedestroy($watermark->getImageResource());
    }
    
    /**
     * Embed textual watermark into image
     * 
     * First parameter is a text to embed into image
     * Second parameter is a position, allowed parameters are: 
     * 	POSITION_TOP_LEFT
     *  POSITION_TOP_CENTER
     * 	POSITION_TOP_RIGHT
     * 	POSITION_CENTER
     * 	POSITION_BOTTOM_LEFT
     * 	POSITION_BOTTOM_CENTER
     * 	POSITION_BOTTOM_RIGHT
     * Third parameter is an assosiative array. That array can contain the following keys:
     * 	'font' - The name of the TrueType font file (can be a URL). 
     * 		Depending on which version of the GD library that PHP is using, 
     * 		it may attempt to search for files that do not begin with a 
     * 		leading '/' by appending '.ttf' to the filename and searching along a library-defined font path.
     * 		(Default is: arial)
     * 	'size' - font point size (Default is: 20)
     * 	'color' - Color index (Default is: #FFFFFF)
     * 	'rotation' - The angle in degrees, with 0 degrees being left-to-right reading text. 
     * 		Higher values represent a counter-clockwise rotation. 
     * 		For example, a value of 90 would result in bottom-to-top reading text.
     * 		(Default is: 0)
     * 	'transparency' - A value between 0 and 100. 0 indicates completely opaque while 100 indicates completely transparent.
     * 		(Default is: 80)
     *  'shadow' - Shadow effect in pixels
     *  	(Default is: 1)
     * 
     * @param string $text
     * @param int $position
     * @param array $params
     * 
     */
    public function watermarkText($text, $position=self::POSITION_CENTER, $params=null)
    {
    	$font = 'arial';
    	$size = 20;
    	$color = '#FFFFFF';
    	$rotation = 0;
    	$transparency = 80;
    	$shadow = 1;
    	if (isset($params['font'])) {
    		$font = $params['font'];
    	}
    	if (isset($params['size'])) {
    		$size = $params['size'];
    	}
    	if (isset($params['color'])) {
    		$color = $params['color'];
    	}
    	if (isset($params['rotation']) && $params['rotation'] > 0 && $params['rotation'] <= 360) {
    		$rotation = $params['rotation'];
    	}
    	if (isset($params['transparency']) && $params['transparency'] >= 0 && $params['transparency'] <= 100 ) {
    		$transparency = $params['transparency'];
    	}
    	if (isset($params['shadow'])) {
    		$shadow = $params['shadow'];
    	}
    	$box = imagettfbbox($size, $rotation, $font, $text);
        $x0 = min($box[0], $box[2], $box[4], $box[6]);
        $x1 = max($box[0], $box[2], $box[4], $box[6]);
        $y0 = min($box[1], $box[3], $box[5], $box[7]);
        $y1 = max($box[1], $box[3], $box[5], $box[7]);
        $watermarkWidth = abs($x1 - $x0);
        $watermarkHeight = abs($y1 - $y0);
        switch ($position) {
            case self::POSITION_TOP_LEFT:
                $y = -$y0 + self::MARGIN;
                $x = -$x0 + self::MARGIN;
                break;
            case self::POSITION_TOP_CENTER:
                $y = -$y0 + self::MARGIN;
                $x = $this->getWidth() / 2 - $watermarkWidth / 2 - $x0;
                break;
            case self::POSITION_TOP_RIGHT:
                $y = -$y0 + self::MARGIN;
                $x = $this->getWidth() - $x1 - self::MARGIN;
                break;
            case self::POSITION_CENTER:
            default:
                $y = $this->getHeight() / 2 - $watermarkHeight / 2 - $y0;
                $x = $this->getWidth() / 2 - $watermarkWidth / 2 - $x0;
                break;
            case self::POSITION_BOTTOM_LEFT:
                $y = $this->getHeight() - $y1 - self::MARGIN;
                $x = -$x0 + self::MARGIN;
                break;
            case self::POSITION_BOTTOM_CENTER:
                $y = $this->getHeight() - $y1 - self::MARGIN;
                $x = $this->getWidth() / 2 - $watermarkWidth / 2 - $x0;
                break;
            case self::POSITION_BOTTOM_RIGHT:
                $y = $this->getHeight() - $y1 - self::MARGIN;
                $x = $this->getWidth() - $x1 - self::MARGIN;
                break;
        }
        $color = trim($color, '#');
        $red = hexdec(substr($color, 0, 2));
        $green = hexdec(substr($color, 2, 2));
        $blue = hexdec(substr($color, 4, 2));
        
        $alpha = 127 * (100 - $transparency) / 100; 
    	if ($shadow) {
        	$gray = imagecolorallocatealpha($this->getImageResource(), 0, 0, 0, $alpha);
        	imagettftext($this->getImageResource(), $size, $rotation, $x-$shadow, $y-$shadow, $gray, $font, $text);
        }
        $color = imagecolorallocatealpha($this->getImageResource(), $red, $green, $blue, $alpha);
        imagettftext($this->getImageResource(), $size, $rotation, $x, $y, $color, $font, $text);
        
    }
    
    /**
     * Save image to $destFileName
     * @param string $destFileName
     */
    public function saveImg($destFileName = null)
    {
        if ($destFileName) {
    		$this->setDestFileName($destFileName);
    	} else if (!$this->getDestFileName()) {
    		$this->_setDestFileName();
    	}
    	switch ($this->getType()) {
            case IMAGETYPE_GIF:
                return imagegif($this->getImageResource(), $this->getDestFileName());
                break;
            case IMAGETYPE_JPEG:
                return imagejpeg($this->getImageResource(), $this->getDestFileName(), $this->getQuality());
                break;
            case IMAGETYPE_PNG:
                return imagepng($this->getImageResource(), $this->getDestFileName(), $this->getQuality());
                break;
            default:
             	throw new Exception("PhpImagizer can manipulate with images of type PNG, JPEG or GIF only");
        }
    }
    
	/**
     * Show image back to browser
     */
    public function showImg()
    {
        switch ($this->getType()) {
            case IMAGETYPE_GIF:
                return imagegif($this->getImageResource());
                break;
            case IMAGETYPE_JPEG:
                return imagejpeg($this->getImageResource(), NULL, $this->getQuality());
                break;
            case IMAGETYPE_PNG:
                return imagepng($this->getImageResource(), NULL, $this->getQuality());
                break;
            default:
             	throw new Exception("PhpImagizer can manipulate with images of type PNG, JPEG or GIF only");
        }
    }
        
  	/**
     * @return the $_srcFileName
     */
    public function getSrcFileName()
    {
        return $this->_srcFileName;
    }

	/**
     * @return the $_destFileName
     */
    public function getDestFileName()
    {
        return $this->_destFileName;
    }

	/**
     * @return the $_type
     */
    public function getType()
    {
        return $this->_type;
    }

	/**
     * @param string $srcFileName
     */
    public function setSrcFileName($srcFileName)
    {
        if (!is_readable($srcFileName)) {
        	throw new PhpImagizerException("PhpImagizer can't open source file $srcFileName. Please make sure it exists and readable");
        }
    	$this->_srcFileName = $srcFileName;
    }

	/**
     * @param string $destFileName
     */
    public function setDestFileName($destFileName)
    {
        $writable = true;
    	if (file_exists($destFileName)) {
        	if (!is_writable($destFileName)) {
        		$writable = false;
        	}
        } else {
        	// Check directory
        	$dir = substr($destFileName, 0, strrpos($destFileName, DIRECTORY_SEPARATOR));
        	if (!is_writable($dir)) {
        		$writable = false;
        	} 
        }
    	if (!$writable) {
        	throw new PhpImagizerException("PhpImagizer can't write the destination file $destFileName. Please change access privileges");
        }
    	$this->_destFileName = $destFileName;
    }

	/**
     * @param string $_type
     */
    public function setType($type)
    {
        if (!in_array($type, array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
        	throw new Exception("PhpImagizer can manipulate with images of type PNG, JPEG or GIF only");
        }
        $this->_type = $type;
        
    }
    
    /**
     * @return the $_imageResource
     */
    public function getImageResource()
    {
        return $this->_imageResource;
    }

	/**
     * @param resource $_imageResource
     */
    public function setImageResource($imageResource)
    {
        $this->_imageResource = $imageResource;
    }
    
    /**
     * @return the $_width
     */
    public function getWidth()
    {
        return $this->_width;
    }

	/**
     * @return the $_height
     */
    public function getHeight()
    {
        return $this->_height;
    }

	/**
     * @param int $width
     */
    public function setWidth($width)
    {
        $this->_width = $width;
    }

	/**
     * @param int $height
     */
    public function setHeight($height)
    {
        $this->_height = $height;
    }
    
    /**
     * @return the $_quality
     */
    public function getQuality()
    {
        return $this->_quality;
    }

	/**
     * @param int $quality
     */
    public function setQuality($quality)
    {
        $this->_quality = $quality;
    }
	
    /**
     * Load image
     */
	protected function _load()
    {
        if (is_resource($this->getImageResource())) {
        	return;
        }
    	if (!$this->getType()) {
            $this->_imageType();
        }
        $type = $this->getType();
        switch ($type) {
            case IMAGETYPE_GIF:
                $im = imagecreatefromgif($this->getSrcFileName());
                break;
            case IMAGETYPE_JPEG:
                $im = imagecreatefromjpeg($this->getSrcFileName());
                break;
            case IMAGETYPE_PNG:
                $im = imagecreatefrompng($this->getSrcFileName());
                break;
        }
        if (is_resource($im)) {
        	$this->setImageResource($im);
        }
        
        $this->_setDimensions();
    }
    
    /**
     * Set width and height of image resource
     */
    protected function _setDimensions()
    {
    	$this->setWidth(imagesx($this->getImageResource()));
        $this->setHeight(imagesy($this->getImageResource()));
    }
    
    /**
     * Get image type of source file
     * Method will try to get image type from exif extension first 
     * as it faster than GD's getimagesize
     */
    protected function _imageType()
    {
    	// Since exif is much faster than "getimagesize" trying to get information from it
    	if (function_exists('exif_imagetype')) {
    		$this->setType(exif_imagetype($this->getSrcFileName()));
    	} else {
    		$imageData = getimagesize($this->getSrcFileName());
    		$this->setType($imageData[2]);
    	}
    }
    
    /**
     * Resize image to $width and $height
     * @param int $width
     * @param int $height
     */
    protected function _resize($width, $height)
	{
		$imgTemp = ImageCreateTrueColor($width, $height);
	    $bgc = ImageColorAllocate($imgTemp, 0xD0 , 0xD0, 0xB8);
        ImageFilledRectangle($imgTemp, 0, 0, $width, $height, $bgc);
        imagecopyresampled($imgTemp, $this->getImageResource(), 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
		$this->setImageResource($imgTemp);
		$this->_setDimensions();
	}
	
	/**
	 * 
	 * Crop image
	 * @param int $trg_x
	 * @param int $trg_y
	 * @param int $trg_w
	 * @param int $trg_h
	 */
	protected function _crop($trg_x, $trg_y, $trg_w, $trg_h)
	{
		$src_w = $trg_w;
		$src_h = $trg_h;
		$img_temp = ImageCreateTrueColor($trg_w, $trg_h);
	    $bgc = ImageColorAllocate($img_temp, 0xD0 , 0xD0, 0xB8);
      	ImageFilledRectangle($img_temp, 0, 0, $trg_w, $trg_h, $bgc);
		imagecopyresampled($img_temp, $this->getImageResource(), 0, 0, $trg_x, $trg_y, $trg_w, $trg_h, $src_w, $src_h);
		$this->setImageResource($img_temp);
		$this->_setDimensions();
	}
	
	/**
	 * Set default destination file name
	 * Method will set file name based on dimension of target image, 
	 * so if source for file is "Penguins.gif" and target image size is 300x400,
	 * destination file name would be: Penguins300x400.gif
	 */
	protected function _setDestFileName()
	{
		$srcFilename = $this->getSrcFileName();
		$destFilename = preg_replace('/(.*)(\..{3})$/', '${1}' . $this->getWidth() . 'x' . $this->getHeight() . '${2}', $srcFilename);
		$this->setDestFileName($destFilename);
	}
}
Return current item: PHP Imagizer - Image Manipulator