Community Pick: Many members of our community have endorsed this article.
Editor's Choice: This article has been selected by our editors as an exceptional contribution.

Use PHP to Make an Image Thumbnail

Published:
Updated:
Introduction
Many web sites contain image galleries; a common design for these galleries includes a page with a collection of thumbnail images.  You can click on each of the thumbnail images to see the larger version of the image.  This is easily implemented by using the HTML anchor tag around the HTML img tag.  You will also need the GD library.  GD must be configured into PHP, and it's installed in most commercial PHP installations.  More information on the GD library is available here:
http://php.net/manual/en/image.requirements.php
http://libgd.bitbucket.org/

How PHP Handles Images
Inside your PHP code you can have two kind of images.  One kind is a string of binary data that represents the image.  This is the kind of image information you would store in your server file system to create an image file you would use in HTML tags.  If you want to manipulate the size or appearance of an image, you need a different representation of the image.  Fortunately the GD library allows us to create a PHP resource that represents the image.  The GD functions allow us to perform operations on the image resource in ways that are similar to the ways we would use a data base query resource, passing the resource to different image manipulation functions and recovering information from the resource.  Once our work is done and we are ready to save or display the image, PHP has functions that turn the resource back into a binary string.

Example of the Use Case
The code snippet shows how to use GD for image manipulation.  As you can see from the use case example on lines 6-8, we can put this script into an HTML image tag.  The script takes three arguments (lines 11-14).  The "img" argument is the URL of the image.  The "w" and "h" arguments are the desired width and height.  In a real-world application you might want to filter this input to ensure that the URL pointed to one of your images, and to ensure that the requested width and height were sensible values.  Parenthetical note: Because we do not constrain "w" and "h", you can also use this script to enlarge an image!

Creating the Thumbnail Image Resource
Our first step will be to create the thumbnail image resource (lines 16-22).  We use imageCreateTrueColor() to create an image resource with the pixel dimensions that came from the GET request arguments.  By default the image is filled with black pixels, but we want the background to be transparent, so we must give GD some more information.  We use imageSaveAlpha() to tell the GD library to use the complete alpha channel.  We use imageColorAllocateAlpha() to tell the image resource that we want a transparent color, then we flood-fill the image with the transparent color.
http://php.net/manual/en/function.imagecreatetruecolor.php
http://php.net/manual/en/function.imagesavealpha.php
http://php.net/manual/en/function.imagecolorallocatealpha.php
http://php.net/manual/en/function.imagefill.php

Acquiring the Original Image Resource
Now that our thumbnail image resource is ready, we need to get the original image.  Our first step is to get the image dimensions with getImageSize().  If this function fails it is usually because the image URL points to a missing file or a file that is not an image.  In any case, failure to get the image dimensions means the script cannot continue, so we test for success (lines 24-33).
http://php.net/manual/en/function.getimagesize.php

The second step in getting the original image requires us to know what kind of image we have.  PHP uses different image functions to create image resources from different file types.  This script is set up to handle JPG and PNG inputs.  Other inputs could be added, such as GIF or BMP, but those are realtively rare in image galleries.  It's easy enough to use the file extension as an indicator of the image type, so we isolate and normalize the extension (line 35-39).  Then we use a switch/case control structure to choose the right "imageCreateFrom()" function (lines 41-54).  If you're interested in enhanced error recovery, there is a good example on the PHP.net man page for ImageCreateFromJPEG().
http://php.net/manual/en/function.imagecreatefromjpeg.php
http://php.net/manual/en/function.imagecreatefrompng.php

Computing Dimensions and Centering the Thumbnail
We compute the ratios of the requested thumbnail size to the original image size (lines 56-59).  Because we want to preserve the image proportions (aspect ratio) in the thumbnail without stretching or squeezing either the width or height, we choose the smaller ratio and apply this to the original image dimensions (lines 61-63).

In this application we want the thumbnail centered on the transparent background with padding either top-and-bottom or left-and-right to fill the requested dimensions.  We compute the offsets from the top left position (lines 65-67).  We divide the offsets by 2 to accomplish the centering process.

Copying the Original Image into the Thumbnail Resource
Now that we have computed the dimensions and offsets for our thumbnail image, it is time to copy and resample the original image into the thumbnail (lines 70-82).  We use imageCopyResampled() to accomplish this transformation.  Since we are using a destination thumbnail image resource created with imageCreateTrueColor() we will get very good-looking output.
http://php.net/manual/en/function.imagecopyresampled.php

Sharpening the Thumbnail
I saw this tip on the PHP.net web site and found that it works beautifully (lines 84-92).  The sharpened images look snappy, even at a small size.  You might want to test the script both with and without sharpening to see the effect.
http://php.net/imageconvolution#104006

Saving and Sending the Thumbnail Image
All the heavy lifting is complete.  We can store the image in a "thumbs" library (lines 95-96).  We can send a PNG header, and use imagePNG() to send the image to the client browser (lines 99-100).  We choose the PNG format for this task because JPG images do not support transparency and the JPG version of this image would have black bars in the empty space.  

A few years ago we would have been wary of using PNG instead of JPG, because JPG images are inherently smaller and "lighter weight."  PNG images offer some compression, though not as much as JPG images can achieve.  This is because JPG compression uses a lossy compression algorithm.  The tradeoffs around higher compression (lower bandwidth) are not as important today as they were a few years ago.  Everyone's internet connections have gotten faster.  Modern browsers can render alpha transparency.

If you're using this script or a derivative work to build a web page, your logic might include looking for the thumbnail image file and if you find it, sending it with readFile().  If you did not find the thumbnail image file, then the processing in this thumbnail script could be invoked to write the PNG onto your server's file system in your "thumbs" directory.  There are some excellent notes on the PHP.net man page for imagePNG().
http://php.net/manual/en/function.imagepng.php
http://php.net/manual/en/function.readfile.php

Clean Up
Image processing requires a lot of memory and our final task is to release the memory (lines 102, et seq).  While this is not an important requirement in this script because the script ends after processing one image, it is still a good practice and it will be necessary in scripts that process several images.
http://php.net/manual/en/function.imagedestroy.php

 
<?php // demo/EE_image_thumbnail.php
                      error_reporting(E_ALL);
                      
                      
                      // RESIZE AN IMAGE TO FIT INSIDE A DEFINED TRANSPARENT SPACE
                      // SAMPLE USE CASES:
                      // <img src="http://www.iconoun.com/demo/EE_image_thumbnail.php?w=300&h=187&img=images/image_600x374.jpg" />
                      // <img src="http://www.iconoun.com/demo/EE_image_thumbnail.php?w=150&h=300&img=images/image_600x374.png" />
                      
                      
                      // ACQUIRE THE URL ARGUMENTS - MAY NEED SOME SANITY TESTS?
                      $thumb_w   = $_GET["w"];
                      $thumb_h   = $_GET["h"];
                      $image_url = $_GET["img"];
                      
                      // CREATE THE THUMBNAIL IMAGE RESOURCE
                      $thumb = imageCreateTrueColor($thumb_w, $thumb_h);
                      
                      // FILL THE THUMBNAIL WITH TRANSPARENT
                      imageSaveAlpha($thumb, TRUE);
                      $empty = imageColorAllocateAlpha($thumb,0x00,0x00,0x00,127);
                      imageFill($thumb, 0, 0, $empty);
                      
                      // TRY TO GET ORIGINAL IMAGE DIMENSIONS
                      $array = @getImageSize($image_url);
                      if ($array)
                      {
                          list($image_w, $image_h) = $array;
                      }
                      else
                      {
                          trigger_error("NO IMAGE $image_url", E_USER_ERROR);
                      }
                      
                      // ACQUIRE THE ORIGINAL IMAGE EXTENSION
                      $ext = explode('.', $image_url);
                      $ext = end($ext);
                      $ext = strtoupper($ext);
                      $ext = trim($ext);
                      
                      // USING THE EXTENSION, ACQUIRE THE IMAGE RESOURCE
                      switch($ext)
                      {
                          case 'JPG' :
                          case 'JPEG' :
                              $image = imagecreatefromjpeg($image_url);
                              break;
                      
                          case 'PNG' :
                              $image = imagecreatefrompng($image_url);
                              break;
                      
                          default : trigger_error("UNKNOWN IMAGE TYPE: $image_url", E_USER_ERROR);
                      }
                      
                      // GET THE LESSER OF THE RATIO OF THUMBNAIL H OR W DIMENSIONS
                      $ratio_w = ($thumb_w / $image_w);
                      $ratio_h = ($thumb_h / $image_h);
                      $ratio   = ($ratio_w < $ratio_h) ? $ratio_w : $ratio_h;
                      
                      // COMPUTE THUMBNAIL IMAGE DIMENSIONS
                      $thumb_w_resize = $image_w * $ratio;
                      $thumb_h_resize = $image_h * $ratio;
                      
                      // COMPUTE THUMBNAIL IMAGE CENTERING OFFSETS
                      $thumb_w_offset = ($thumb_w - $thumb_w_resize) / 2.0;
                      $thumb_h_offset = ($thumb_h - $thumb_h_resize) / 2.0;
                      
                      // COPY THE IMAGE TO THE CENTER OF THE THUMBNAIL
                      imageCopyResampled
                      ( $thumb              // DESTINATION IMAGE
                      , $image              // SOURCE IMAGE
                      , $thumb_w_offset     // DESTINATION X-OFFSET
                      , $thumb_h_offset     // DESTINATION Y-OFFSET
                      , 0                   // SOURCE X-OFFSET
                      , 0                   // SOURCE Y-OFFSET
                      , $thumb_w_resize     // DESTINATION WIDTH
                      , $thumb_h_resize     // DESTINATION HEIGHT
                      , $image_w            // SOURCE WIDTH
                      , $image_h            // SOURCE HEIGHT
                      )
                      ;
                      // SHARPEN THE THUMBNAIL SEE php.net/imageconvolution#104006
                      $sharpenMatrix = array
                      ( array( -1.2, -1.0, -1.2 )
                      , array( -1.0, 20.0, -1.0 )
                      , array( -1.2, -1.0, -1.2 )
                      )
                      ;
                      $divisor = array_sum(array_map('array_sum', $sharpenMatrix));
                      $offset  = 0;
                      imageConvolution($thumb, $sharpenMatrix, $divisor, $offset);
                      
                      // SAVE THE THUMBNAIL IMAGE IN A "THUMBS" DIRECTORY
                      $bname = basename($image_url);
                      imagePNG($thumb, "thumbs/$bname");
                      
                      // SHOW THE NEW THUMB IMAGE
                      header('Content-type: image/png');
                      imagePNG($thumb);
                      
                      // RELEASE THE MEMORY USED BY THE IMAGE RESOURCES
                      imageDestroy($thumb);
                      imageDestroy($image);

Open in new window

Summary
We have seen how we can use PHP to create and modify image resources, and how to perform image resizing and centering.  More examples are available on the PHP.net web site, both on the examples page, and in the user-contributed notes for the image functions.
http://php.net/manual/en/image.examples.php

Please give us your feedback!
If you found this article helpful, please click the "thumb's up" button below. Doing so lets the E-E community know what is valuable for E-E members and helps provide direction for future articles.  If you have questions or comments, please add them.  Thanks!
 
7
8,463 Views

Comments (3)

Jason C. LevineDon't talk to me.
CERTIFIED EXPERT

Commented:
Ray,

This is an excellent and very useful script.  Nicely documented...thank you.  Are the functions used above part of a "standard" PHP deployment on the bigger shared hosts like GoDaddy and Dreamhost?
Most Valuable Expert 2011
Author of the Year 2014

Author

Commented:
Hey, Jason.  My guess is "yes."  I have never seen a PHP installation (at least not in the last 4 years) that did not have the GD extensions.
CERTIFIED EXPERT
Author of the Year 2011
Top Expert 2006

Commented:
Hi Ray,
Another great Article!
Thank you for putting it together.
Vic
(Yes vote above.)

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.