Skip to content

December 28, 2010

1

How To: PHP Thumbnails – Resize images with PHP

I have revisited this subject here: Revisited: PHP Thumbnails

We all have been in situation where we allow users to upload images for content items or profile pictures. They’ll just upload huge images without considering bandwidth and disk space. Soon you have hundreds images above 2MB in size cluttering your precious harddisk space and taking up all of the bandwidth with just a few pageviews.

So how do you conquer this problem? Well, resize the images automatically. Keeping their ratio and quality but reducing their size significantly.

I assume you have some knowledge with HTML and know how to upload a file. Therefor in these examples I use the file example.png and assume its in the images/ folder.

First the class that we will use to resize the image

<?php
/**
 * Class createImage
 *
 * @author Thijs Damen
 * @desc Creates a resized image from an existing image
 *
 */
class createImage {

	/*Folder where the current image can be found*/
	private $RootFolder;

	/*Folder relative from RootFolder to write the image to*/
	private $dstFolder;

	/*Name of the image*/
	private $ImageName;

	/*Image Extension*/
	private $ImageExtention;

	/*Maximum width for image*/
	private $img_maxWidth;
	/*Maximum height for image*/
	private $img_maxHeight;

	/*Current width of the image*/
	private $img_curWidth;
	/*Current height of the image*/
	private $img_curHeight;

	/*New width of the image*/
	private $img_newWidth;

	/*New height of the image*/
	private $img_newHeight;

	/*Quality of the new image*/
	private $imgQuality;

	/*Thumb of the image*/
	private $thumb;

	/*
	 * Constructor
	 * Recieves all parameters and immediatly creates the new image
	 */
	public function __construct($rootfolder, $imagename, $dstfolder, $maxwidth, $maxheight, $quality = 100) {
		$this->RootFolder 		= 	$rootfolder;
		$this->ImageName		=	$imagename;
		$this->dstFolder		= 	$dstfolder;
									//Neat trick that will get everything from the last . as a string (aka. extension)
		$this->ImageExtention 	=   end(explode(".", $imagename));
		$this->img_maxWidth		= 	$maxwidth;
		$this->img_maxHeight	=	$maxheight;
		$this->imgQuality		=	$quality;

		$this->calcImgSize();
	}

	/*
	 * Smart function that will calculate the new width and height of the image
	 */
	private function calcImgSize() {
		$src = getimagesize($this->RootFolder.$this->ImageName);
		$this->img_curWidth 	= 	$src[0];
		$this->img_curHeight	= 	$src[1];

		//Some calculation to determine wether the layout it landscape or portrait
		if(($this->img_curWidth / $this->img_maxWidth) > ($this->img_curHeight / $this->img_maxHeight)) {
			// landscape mode so recalculate based on width
			if ($this->img_curWidth > $this->img_maxWidth) {
				$this->img_newWidth = intval($this->img_maxWidth);
				$this->img_newHeight = intval($this->img_curHeight * ($this->img_maxWidth / $this->img_curWidth));
			} else {
				$this->img_newWidth = $this->img_curWidth;
				$this->img_newHeight = $this->img_curHeight;
			}
		} else {
			// portrait mode so recaulculate on height
			if ($this->img_curHeight > $this->img_maxHeight) {
				$this->img_newHeight = intval($this->img_maxHeight);
				$this->img_newWidth = intval($this->img_curWidth * ($this->img_maxHeight / $this->img_curHeight));
			} else {
				$this->img_newWidth = $this->img_curWidth;
				$this->img_newHeight = $this->img_curHeight;
			}
		}
		//GD Function that returns an image identifier based on width and height
		$this->thumb = imagecreatetruecolor($this->img_newWidth, $this->img_newHeight);
		if (!$this->createImage()) {
			return false;
		}
	}

	/*
	 * Create the new image based on extension
	 */
	private function CreateImage() {
		/*
		 * Switch the extension. so we know what type of image we are dealing with
		 * All of these will use their respecitve create function (imagecreatefrom)
		 * Create a copy from it and write it to the disk
		 */
		switch ($this->ImageExtention) {
			case "jpg":
			case "jpeg":
				header("Content: image/jpeg");
				$imgcreate = imagecreatefromjpeg($this->RootFolder.$this->ImageName);
				$imgcopy = imagecopyresampled($this->thumb, $imgcreate, 0,0,0,0, $this->img_newWidth, $this->img_newHeight, $this->img_curWidth, $this->img_curHeight);
				return imagejpeg($this->thumb,$this->RootFolder.$this->dstFolder.$this->ImageName,$this->imgQuality);
			break;
			case "png":
				header("Content: image/png");
				$imgcreate = imagecreatefrompng($this->RootFolder.$this->ImageName);
				$imgcopy = imagecopyresampled($this->thumb, $imgcreate, 0,0,0,0, $this->img_newWidth, $this->img_newHeight, $this->img_curWidth, $this->img_curHeight);
				/*
				 *  This is a special case. Where imagejpeg and imagegif take their quality parameter as 0 to 100.
				 *  0 being the worst and 100 being best. imagepng expects 0 to 9, 0 being the best. 9 being the worst.
				 *  So we have to do some calculation for the quality
				 */
				$quality = ($this->imgQuality - 100) / 11.11;
				$this->imgQuality = round(abs($quality));
				return imagepng($this->thumb,$this->RootFolder.$this->dstFolder.$this->ImageName, $this->imgQuality);
			break;
			case "gif":
				header("Content: image/gif");
				$imgcreate = imagecreatefromgif($this->RootFolder.$this->ImageName);
				$imgcopy =  imagecopyresampled($this->thumb, $imgcreate, 0,0,0,0, $this->img_newWidth, $this->img_newHeight, $this->img_curWidth, $this->img_curHeight);
				return imagegif($this->thumb,$this->RootFolder.$this->dstFolder.$this->ImageName,$this->imgQuality);
			break;
		}
	}
}

How to use this class? Simple:

I have an image in the images/ folder named image.png. It is 4096×3072 pixels in size (and 1.4MB big) currently and I want to resize it to a maximum of 512×512.

new createImage("images/", "image.png", "thumbs/", 512, 512, 80);

This will now create a image in images/thumbs/, still named image.png of size: 512*384 with a little less quality then the original, but little chance you will actually notice the difference (also, it is only 56KB big, which is 2500% smaller(!) then the original).

The best part about this. I can do the same with my JPEGs and GIFs without a hassle. look

new createImage("images/","image.jpg", "thumbs/", 512, 512, 80);

And this will do exactly the same just for the JPG extension. So instead of having to remember 3 different functions, I can just use a single class which holds all the logic for me.

There are some prerequisites. The destFolder has to be writable and you have to have the GD library installed. Also, it might be necessary to temporarily increase the memory limit of php.

ini_set('memory_limit', '256M');

I hope this helps someone with resizing their images in a good way. Keeping proportions and reducing image size significantly.

Share your thoughts, post a comment.

(required)
(required)

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments