PHP Thumbnails on the Fly

In the MegaGallery project, we used the EXIF library in PHP to extract the thumbnails from the image itself. However, what do we do if we do not have EXIF installed or available through our web server provider? One possibility is to use the GD library. The GD library will allow us to create a thumbnail using the image itself.

The code in this article is based off an article by  Christian Heilmann. I have made a few changes, most notably the way that second size for the thumbnail is calculated. For details about the math behind this change, see my post Resizing Images.

We will create two functions that will allow us to create thumbnails on the fly. In fact, you might prefer this method to the one presented in the MegaGallery project. You will need to check your PHP install to make sure you have the GD Library installed. Just create a PHP file on your server with the command phpinfo() in it. This will give you details about what libraries are installed on your server. The section you are looking for will look something like the image below.

GD libray entry in phpinfo()

GD libray entry in phpinfo()

We will only set up our functions to handle both JPEG and PNG image file types. Other file types are possible, but these are the two most common. If you need others, you can add them later.

The creation of the thumbnail is a 5 step process:

  1. Read the image file
  2. Resize the image
  3. Create new image with the resized width and height
  4. Resample image to new image size
  5. Write new image

The create_thumb() Function

function create_thumb($name,$filename,$new_w,$new_h) {
 $system=explode(".",$name);
 if (preg_match("/jpg|jpeg/",$system[1])){$src_img=imagecreatefromjpeg($name);}
 if (preg_match("/png/",$system[1])){$src_img=imagecreatefrompng($name);}
 $old_x=imageSX($src_img);
 $old_y=imageSY($src_img);
 if ($old_x > $old_y) {
 $thumb_w=$new_w;
 $thumb_h = ($new_w * $old_y) / $old_x;
 }
 if ($old_x < $old_y) {
 $thumb_w = ($new_h * $old_x) / $old_y;
 $thumb_h=$new_h;
 }
 if ($old_x == $old_y) {
 $thumb_w=$new_w;
 $thumb_h=$new_h;
 }
 $dst_img=ImageCreateTrueColor($thumb_w,$thumb_h);
 imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);
 if (preg_match("/png/",$system[1])) {
 imagepng($dst_img,$filename);
 } else {
 imagejpeg($dst_img,$filename);
 }
imagedestroy($dst_img);
imagedestroy($src_img);
}

In line 1, we have our function definition. we pass it four variables: 1. the name of the existing image, 2. a file name for the thumbnail, 3. the width for the thumbnail, and 4. the height for the thumbnail.

The first thing we need to know is the type of file we are dealing with. Is it a JPG or PNG? We do this by using the explode() function to isolate the files extension (line 2), which gives us the array $system containing everything but the extension at index 0 and the extension in index 1. If it is a JPG, we use the GD function imagecreatefromjpeg() to read the image file into memory (line 3). However, if it is a PNG, we use the GD function imagecreatefrompng() to read the image file into memory (line 4).

In lines 5 and 6, we use the GD functions imageSX() and imageSY() to get the width and height of the image. Lines 7-18 contain our calculations for the thumbnails width and height. If the image is wider than it is tall, we recalculate the height. If the image height is more than the width, we recalculate the width. If the width and height are the same (it is a square image), we just keep the width and height passed to the function. This is done to maintain the aspect ratio of the image in the thumbnail.

In line 19 and 20, we create a new image in memory that is the width and height we calculated for our thumbnail. For this, we use the GD function ImageCreateTrueColor() and pass it our thumbnail width and height. We use the GD function imagecopyresampled() to resample the original image into our thumbnail. We pass it the object for the thumbnail, the original image, the xy start position in the thumbnail (0,0 in our case), the starting xy in the original (again 0,0), the width and height of the thumbnail, and the width and height of the original image.

Lines 21-25, use the GD functions imagepng() and imagejpeg() to write the thumbnails to the thumbnail filename. Line 26-27 destroy the two image objects we created in memory. It’s a good practice to free up this memory once we are done.

The Workhorse: create_thumb_tag()

This function is our control center. While we could call create_thumb() directly, it is better to have some control over how and when it is called. Case and point: if the thumbnail already exists, we don’t need to make another one.

define("IMAGE_DIR", "pix");
define("THUMB_DIR", "thumbs");
define("THUMB_X", 196);
define("THUMB_Y", 147);
define("THUMB_PREFIX", "tn_");

function create_thumb_tag($image) {
    $thumbfile = THUMB_PREFIX . $image;
    $fullpath = THUMB_DIR . '/' . $thumbfile;
    if(!file_exists($fullpath)) {
        create_thumb(IMAGE_DIR . '/' . $image, $fullpath, THUMB_X, THUMB_Y);
    }
    $size = getimagesize($fullpath);
    return "<img $size[3] src="$fullpath" alt="$image Thumbnail" />";
}

We start out by defining 5 constants: IMAGE_DIR, THUMB_DIR, THUMB_X, THUMB_Y, and THUMB_PREFIX. By naming these constants in this manner, we only have to change them in one place, but we can use them anywhere. The THUMB_X and THUMB_Y are the max width and height for our thumbnails.

The function declaration in line 7 is pretty simple. We just pass it the name of the image. In line 8, we add the thumbnail prefix to the image file name. Line 9 creates a full path to the thumbnail file. Line 10-12 check to see if the thumbnail already exist. If not, it creates one by calling create_thumb(). Line 13 uses GD’s getimagesize() function to get an array which we use in line 14 to return a formatted HTML img tag.

Conclusion

The GD method for creating thumbnails has a few advantages over the EXIF method. With GD, you are able to create thumbnails on the fly, and speed up the process by not having to extract or create a thumbnail if one already exists. However, you do loose the advantage of being able to extract the comments like we did with EXIF. For comments using the GD method, you will need another way to record and retrieve comments (maybe a database, flat file, or XML file.) If you are lucky enough to have both modules, you could use GD for thumbnails and EXIF for comments.

This is just one more method for creating thumbnails with PHP. I like the solution because it can greatly increase the rendering speed of a large gallery of images.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s