View Full Version : Resizing images on the fly with gd/gd2 - adding a cache


mr chris
30-01-2008, 10:11
Right, I'm building a site for a client (or at least planning it) and I need to be able to display the same image at several sizes - which I know is perfectly possible using the gd image library (which my servers have installed. I can't install imagemagick or netpbm, so don't ask!).

Now, the thing is... I need to build a cache function in so I'm not generating the same image over and over and over...

I've found a few examples, for example the one below (which works perfectly aside from a cache).

<?php

function resizeImage($originalImage,$toWidth,$toHeight){

// Get the original geometry and calculate scales
list($width, $height) = getimagesize($originalImage);
$xscale=$width/$toWidth;
$yscale=$height/$toHeight;

// Recalculate new size with default ratio
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));
}

// Resize the original image
$imageResized = imagecreatetruecolor($new_width, $new_height);
$imageTmp = imagecreatefromjpeg ($originalImage);
imagecopyresampled($imageResized, $imageTmp, 0, 0, 0, 0, $new_width, $new_height, $width, $height);

return $imageResized;
}

?>

Which is called onto the page with the following

<?php
//Resize the image
$myimg1 = resizeImage('image.jpg',300,300);
// Creat the new file
imagejpeg($myimg1,'resizedimage.jpg',100);
//Display the new image
echo '<img src="resizedimage.jpg" alt="alt text" />';
?>


Can anyone help? HTML/CSS is a walk in the park, but I'm not a hardcore coder, and so whilst I can follow how this works, I can't write it myself!

Thanks guys!

adaline
30-01-2008, 10:58
How do the images get there in the first place?

mr chris
30-01-2008, 11:10
They're uploaded to the server separately when I add an entry - the CMS (expression engine) I use will allow me to call them into place without much hassle, it's just what happens to them *when* I call them that's the issue.

adaline
30-01-2008, 11:33
They're uploaded to the server separately when I add an entry - the CMS (expression engine) I use will allow me to call them into place without much hassle, it's just what happens to them *when* I call them that's the issue.
In this case you will need some way to check if the images were resized before, one way would be to have a table in a db with names of the resized files other way would be to actually check the image directory for files. The db way is faster and less strainious for the server - which in turn means much faster loading page for the end user, il go through in psudo code for this instance:

function display_pic(picture_name){
result = mysql_query('Select count(id) from images where name=picture_name);
if(result==0){
resize_and_store_image(picture_name,picture_name_s mall);
mysql_query('Insert into images (name) values picture_name');
}
display picture_name_small;
}

karl101
30-01-2008, 12:08
You could check if it exists with is_file if it doesn't then do the resize thing then save it out.

http://docs.php.net/manual/en/function.is-file.php

getimagesize will tell you the size of an image, you could use that to check

http://docs.php.net/manual/en/function.getimagesize.php

K.

mr chris
30-01-2008, 14:05
You could check if it exists with is_file if it doesn't then do the resize thing then save it out.

http://docs.php.net/manual/en/function.is-file.php

getimagesize will tell you the size of an image, you could use that to check

http://docs.php.net/manual/en/function.getimagesize.php

K.

That's what I was thinking.

The DB route is out of my level of expertise, so the manual checking of the directory would be my easiest option.

Free bag of chips (or hosting!) for anyone who can actually write this snippet of code for me.

Ghozer
30-01-2008, 14:34
Heres what I use...


$thumbquality = "75";
$maxthumbwidth = "130";
$maxthumbheight = "130;

$source = stripslashes('../gallery/'.$_GET['gallery'].'/'.$_GET['img']);
$origin = stripslashes('../gallery/'.$_GET['gallery']);
$path = pathinfo($source);

$hash = md5($_GET['img']);

switch(strtolower($path["extension"]))
{
case "jpeg":
case "jpg":
$original = imagecreatefromjpeg($source);
break;
case "gif":
$original = imagecreatefromgif($source);
break;
case "png":
$original = imagecreatefrompng($source);
break;
default:
break;
}
$xratio = $maxthumbwidth / (imagesx($original));
$yratio = $maxthumbheight / (imagesy($original));

if($xratio < $yratio) { $thumb = imagecreatetruecolor($maxthumbwidth,floor(imagesy( $original) * $xratio)); }
else { $thumb = imagecreatetruecolor(floor(imagesx($original) * $yratio), $maxthumbheight); }

imagecopyresampled($thumb, $original, 0, 0, 0, 0, imagesx($thumb)+1,imagesy($thumb)+1,imagesx($origi nal),imagesy($original));
imagedestroy($original);

imagejpeg($thumb, $origin . '/cache/' . $hash . '.jpg', $thumbquality);

header('Content-type: image/jpeg');
header('Content-transfer-encoding: binary');
imagejpeg($thumb, null, $thumbquality);
imagedestroy($thumb);


then I just use <img src="gallery_thumb.php?image=FILENAME.JPG" /> in my html..

this generates the cache into a folder called cache from the original images, I check if cache exists in my Gallery script (not thumbnail generation) and use the cached thumb if it does exist..

Directory structure =

htmldocs
htmldocs/includes/gallery.php
htmldocs/includes/gallery_thumb.php
htmldocs/gallery/Folder 1/
htmldocs/gallery/Folder 1/IMAGE1.jpg
htmldocs/gallery/Folder 1/IMAGE2.jpg
htmldocs/gallery/Folder 1/cache/CACHE1.jpg
htmldocs/gallery/Folder 1/cache/CACHE2.jpg
htmldocs/gallery/Folder 2/IMAGE1.jpg
htmldocs/gallery/Folder 2/IMAGE2.jpg
htmldocs/gallery/Folder 2/cache/CACHE1.jpg
htmldocs/gallery/Folder 2/cache/CACHE2.jpg

as for the gallery, I use

$out .= '<table border="0" width="100%" cellspacing="0" cellpadding="3" class="forums">
<tr>';

foreach(glob($site_info['gal_dir'] . '/' . $gallery . '/*.*') as $path) {
$name = substr(strrchr($path, chr(47)), 1);

$hash = md5($name);
if(glob($site_info['gal_dir'] . '/' . $gallery . '/cache/' . $hash . '.jpg')) {
$cache = $site_info['gal_dir'] . '/' . $gallery . '/cache/' . $hash . '.jpg';
$out .= '<td class="topics_col"><a href="' . $path . '" rel="lightbox[' . $gallery . ']" title="' . $name . '"><img src="' . $cache . '" alt="' . $name . '" /></a><br />' . $name . '</td>';
}
else {
$out .= '<td class="topics_col"><a href="' . $path . '" rel="lightbox[' . $gallery . ']" title="' . $name . '"><img src="includes/gallery_thumb.php?gallery=' . $gallery . '&amp;img=' . $name . '" alt="' . $name . '" /></a><br />' . $name . '</td>';
}
$col++;
if($col == $maxthumb) {
$out .= '</tr><tr>';
$col = 0;
}
}
$out .= '</tr></table>';


to check the images

not 100% fool proof, I could (and probably should) add a couple more checks, but it works (see it at www.sychosis.com)

John
30-01-2008, 15:30
<?php
//Resize the image
$myimg1 = resizeImage('image.jpg',300,300);
// Creat the new file
imagejpeg($myimg1,'resizedimage.jpg',100);
//Display the new image
echo '<img src="resizedimage.jpg" alt="alt text" />';
?>

Change this code to....

<?php

$image = "image.jpg";
$cacheImage = "cache/".$image;

if (!file_exists($cacheImage))
{
$bitmap = resizeImage($image, 300, 300);
imagejpeg($bitmap, $cacheImage, 100);
}

echo '<img src="$cacheImage" alt="alt text" />';

?>

and create a folder with write access called cache

Phanerothyme
30-01-2008, 15:30
They're uploaded to the server separately when I add an entry - the CMS (expression engine) I use will allow me to call them into place without much hassle, it's just what happens to them *when* I call them that's the issue.
have you tried phpthumb?

it can manage its own cache too.

mr chris
30-01-2008, 15:44
have you tried phpthumb?

it can manage its own cache too.

That seems like an excellent idea. :idea: :thumbsup:

liam1412
30-01-2008, 16:29
I can say phpthumb is the best thing I have came across. Highly recommended. Even without the cache its still quick enough