Jul
19
2011

PHP resize large images with imagemagick

Resize with GD

The function imagecopyresampled is used to resize an image with gd library.
Here is a quick example :

function resize_image($src , $dest , $toWidth , $toHeight , $options = array())
{
	if(!file_exists($src))
	{
		die("$src file does not exist");
	}

	//OPEN THE IMAGE INTO A RESOURCE
	$img = imagecreatefromjpeg ($src);	//try jpg

	if(!$img)
	{
		$img = imagecreatefromgif ($src);	//try gif
	}

	if(!$img)
	{
		$img = imagecreatefrompng ($src);	//try png
	}

	if(!$img)
	{
		die("Could Not create image resource $src");
	}

	//ORIGINAL DIMENTIONS
	list( $width , $height ) = getimagesize( $src );

	//ORIGINAL SCALE
	$xscale=$width/$toWidth;
	$yscale=$height/$toHeight;

	//NEW DIMENSIONS WITH SAME SCALE
	if ($yscale > $xscale)
	{
		$new_width = round($width * (1/$yscale));
		$new_height = round($height * (1/$yscale));
	}
	else
	{
		$new_width = round($width * (1/$xscale));
		$new_height = round($height * (1/$xscale));
	}

	//NEW IMAGE RESOURCE
	if(!($imageResized = imagecreatetruecolor($new_width, $new_height)))
	{
		die("Could not create new image resource of width : $new_width , height : $new_height");
	}

	//RESIZE IMAGE
	if(! imagecopyresampled($imageResized, $img , 0 , 0 , 0 , 0 , $new_width , $new_height , $width , $height))
	{
		die('Resampling failed');
	}

	//STORE IMAGE INTO DESTINATION
	if(! imagejpeg($imageResized , $dest))
	{
		die("Could not save new file");
	}

	//Free the memory
	imagedestroy($img);
	imagedestroy($imageResized);

	return true;
}

However the above has some problems. If a jpg image for example , is 5000px x 5000px then imagecreatefromjpg would uncompress it and use large memory ( 5000 x 5000 pixels). And then memory exceeded error might be thrown depending on how much memory is available to php.

Resize with Imagemagick

One possible solution is to use imagemagick. Imagemagick can resize large images by using disk space instead of RAM memory.

To resize an image using imagemagick, the code should be :

//Resize using imagemagick , it is memory efficient, GD fails since images are uncompressed.
try
{
	$img = new Imagick($old_path);
	$img->thumbnailImage(500 , 500 , TRUE);
	$img->writeImage($new_path);

	$count++;
}
catch(Exception $e)
{
	echo 'Caught exception: ',  $e->getMessage(), "\n";
	$error++;
}

This should work where gd fails due to memory limitations.

Memory usage can be limited by using :

$img->setResourceLimit( Imagick::RESOURCETYPE_MEMORY, 5 );

Source

When memory limit is reached , disk space is used for memory.

Other ways of resizing images using imagemagick

<?php
/**
 * Calculate new image dimensions to new constraints
 *
 * @param Original X size in pixels
 * @param Original Y size in pixels
 * @return New X maximum size in pixels
 * @return New Y maximum size in pixels
 */
function scaleImage($x,$y,$cx,$cy) {
    //Set the default NEW values to be the old, in case it doesn't even need scaling
    list($nx,$ny)=array($x,$y);

    //If image is generally smaller, don't even bother
    if ($x>=$cx || $y>=$cx) {

        //Work out ratios
        if ($x>0) $rx=$cx/$x;
        if ($y>0) $ry=$cy/$y;

        //Use the lowest ratio, to ensure we don't go over the wanted image size
        if ($rx>$ry) {
            $r=$ry;
        } else {
            $r=$rx;
        }

        //Calculate the new size based on the chosen ratio
        $nx=intval($x*$r);
        $ny=intval($y*$r);
    }    

    //Return the results
    return array($nx,$ny);
}
?>

Use it like this:

<?php
//Read original image and create Imagick object
$thumb=new Imagick($originalImageFilename);

//Work out new dimensions
list($newX,$newY)=scaleImage(
        $thumb->getImageWidth(),
        $thumb->getImageHeight(),
        $newMaximumWidth,
        $newMaximumHeight);

//Scale the image
$thumb->thumbnailImage($newX,$newY);

//Write the new image to a file
$thumb->writeImage($thumbnailFilename);
?>
$fitbyWidth = (($maxWidth/$w)<($maxHeight/$h)) ?true:false;

if($fitbyWidth){
    $im->thumbnailImage($maxWidth, 0, false);
}else{
    $im->thumbnailImage(0, $maxHeight, false);
}

Maximum width and height

For example if the resized image should have a maximum width of 200px , and maximum height of 82 px , then the limits can be applied easily like this :

// Create thumbnail max of 200x82
$width=$im->getImageWidth();
if ($width > 200)
{
    $im->thumbnailImage(200,null,0);
}

//now check height
$height=$im->getImageHeight();
if ($height > 82)
{
    $im->thumbnailImage(null,82,0);
}

Resources

1. Imagemagick tutorials – http://valokuva.org/?cat=1

2. http://www.php.net/manual/en/function.imagick-thumbnailimage.php

3. http://www.php.net/manual/en/book.imagick.php

Popularity: 5% [?]

3 Comments + Add Comment

  • Thank you for opinion ;)

  • Dear Blogger

    I’m going to change my code from using GD to Imagemagick (Fred’s ImageMagick Scripts inspired me). What should I used to? Included in php ImageMagick or with system() command? What in your opinion is more efficient?

    • Use the php extension for imagemagick.

Leave a comment