Image Thumbnails

By tye on Mar 10, 2005

This uses the GD library to create a thumbnail out of an image.

$infile = path to source image

$outfile = file and path to write the thumbnail to

$maxw = Maximum width of the thumbnail

$maxh = Maximum height of the thumbnail

$stretch = Stretch image if it is smaller than the maxw and maxh
The function will preserve the aspect ratio of the image. If you specify 0 for either $maxw or $maxh then the function will assume that the max width/height can be unlimited (ie, if you specify 0 for $maxw it will only resize the height to $maxh likewise for specifying 0 for $maxh)



By default if the source image is already smaller than the thumbnail size it will not be stretched to the $maxw or $maxh. If you specify TRUE for $stretch it will be stretched if it is already smaller than the $maxw and $maxh parameters.



This function supports PNG, JPEG and GIF formats. Adding new formats shouldn't be hard.

<?php
/*
  Tye Shavik (tye at tye . ca)
*/
function create_thumbnail($infile,$outfile,$maxw,$maxh,$stretch = FALSE) {
  clearstatcache();
  if (!is_file($infile)) {
    trigger_error("Cannot open file: $infile",E_USER_WARNING);
    return FALSE;
  }
  if (is_file($outfile)) {
      trigger_error("Output file already exists: $outfile",E_USER_WARNING);
    return FALSE;
  }

  $functions = array(
    'image/png' => 'ImageCreateFromPng',
    'image/jpeg' => 'ImageCreateFromJpeg',
  );

  // Add GIF support if GD was compiled with it
  if (function_exists('ImageCreateFromGif')) { $functions['image/gif'] = 'ImageCreateFromGif'; }

  $size = getimagesize($infile);

  // Check if mime type is listed above
  if (!$function = $functions[$size['mime']]) {
      trigger_error("MIME Type unsupported: {$size['mime']}",E_USER_WARNING);
    return FALSE;
  }

  // Open source image
  if (!$source_img = $function($infile)) {
      trigger_error("Unable to open source file: $infile",E_USER_WARNING);
    return FALSE;
  }

  $save_function = "image" . strtolower(substr(strrchr($size['mime'],'/'),1));

  // Scale dimensions
  list($neww,$newh) = scale_dimensions($size[0],$size[1],$maxw,$maxh,$stretch);

  if ($size['mime'] == 'image/png') {
    // Check if this PNG image is indexed
    $temp_img = imagecreatefrompng($infile);
    if (imagecolorstotal($temp_img) != 0) {
      // This is an indexed PNG
      $indexed_png = TRUE;
    } else {
      $indexed_png = FALSE;
    }
    imagedestroy($temp_img);
  }

  // Create new image resource
  if ($size['mime'] == 'image/gif' || ($size['mime'] == 'image/png' && $indexed_png)) {
    // Create indexed 
    $new_img = imagecreate($neww,$newh);
    // Copy the palette
    imagepalettecopy($new_img,$source_img);

    $color_transparent = imagecolortransparent($source_img);
    if ($color_transparent >= 0) {
      // Copy transparency
      imagefill($new_img,0,0,$color_transparent);
      imagecolortransparent($new_img, $color_transparent);
    }
  } else {
    $new_img = imagecreatetruecolor($neww,$newh);
  }

  // Copy and resize image
  imagecopyresampled($new_img,$source_img,0,0,0,0,$neww,$newh,$size[0],$size[1]);

  // Save output file
  if ($save_function == 'imagejpeg') {
      // Change the JPEG quality here
      if (!$save_function($new_img,$outfile,75)) {
          trigger_error("Unable to save output image",E_USER_WARNING);
          return FALSE;
      }
  } else {
      if (!$save_function($new_img,$outfile)) {
          trigger_error("Unable to save output image",E_USER_WARNING);
          return FALSE;
      }
  }

  // Cleanup
  imagedestroy($source_img);
  imagedestroy($new_img);

  return TRUE;
}
// Scales dimensions
function scale_dimensions($w,$h,$maxw,$maxh,$stretch = FALSE) {
    if (!$maxw && $maxh) {
      // Width is unlimited, scale by width
      $newh = $maxh;
      if ($h < $maxh && !$stretch) { $newh = $h; }
      else { $newh = $maxh; }
      $neww = ($w * $newh / $h);
    } elseif (!$maxh && $maxw) {
      // Scale by height
      if ($w < $maxw && !$stretch) { $neww = $w; }
      else { $neww = $maxw; }
      $newh = ($h * $neww / $w);
    } elseif (!$maxw && !$maxh) {
      return array($w,$h);
    } else {
      if ($w / $maxw > $h / $maxh) {
        // Scale by height
        if ($w < $maxw && !$stretch) { $neww = $w; }
        else { $neww = $maxw; }
        $newh = ($h * $neww / $w);
      } elseif ($w / $maxw <= $h / $maxh) {
        // Scale by width
        if ($h < $maxh && !$stretch) { $newh = $h; }
        else { $newh = $maxh; }
        $neww = ($w * $newh / $h);
      }
    }
    return array(round($neww),round($newh));
}
?>

Comments

Sign in to comment.
Hawkee   -  Oct 21, 2009

cthaele, It's basically a function that you call with the required parameters.

 Respond  
cthaele   -  Oct 21, 2009

hi,

sorry, but how i can use this script. which way is the right to implement?

thanks for helping me!

regards Chris

 Respond  
tylla   -  Jul 05, 2006

Some hint if you want to use this code for true-color alpha channel transparent images (actually tried it on png-s).
After the

$new_img = imagecreatetruecolor($neww,$newh);

line I added these:

imagealphablending( $new_img, false );
$col = imagecolorallocatealpha( $new_img, 0, 0, 0, 127 );
imagefilledrectangle( $new_img, 0, 0, $neww, $newh, $col );
imagealphablending( $new_img, true );
imageSaveAlpha($new_img, true);

This fills the new image with fully transparent pixels.
The most painful was the last function call, because it took some half an hour to discover that without it the alpha channel isn\'t saved with the image.

 Respond  
Scooder   -  Jun 07, 2006

Works great! Thanks tye, best script I\'ve ever put to use.

 Respond  
tye   -  Jun 06, 2006

Thanks for posting that bug. The scale_dimensions function wasn\'t working for some combinations of numbers. I\'ve rewritten the function and tested it with every combination of numbers I could think of and it seems to work. If it doesn\'t please let me know.

 Respond  
Scooder   -  Jun 05, 2006

I\'ve found a problem with the script (other than this small problem, this script is GREAT!).

I\'ll explain by example:

  • Call the function with a max width of 250 and height of 150
  • Input file that I call function with is 320x320
  • The thumbnail generates the thumbnail at 250x250... ABOVE the maximum height of 150 pixels

Is this a bug? Or is this how it is supposed to work?

 Respond  
tye   -  May 27, 2006

Thanks for the changes.

I put them in the snippet and extended them to work on transparent PNG images.

 Respond  
Hawkee   -  May 14, 2006

Here are some changes I made to support GIF transparencies. I also changed the imagecopyresized function to imagecopyresampled because the quality of the shrunk images was fairly poor. This fixed it right up.

// Create new image

if($function == \'ImageCreateFromGif\')
{
$colorTransparent = imagecolortransparent($source_img);
$new_img = imagecreate($neww,$newh);
imagepalettecopy($new_img,$source_img);
imagefill($new_img,0,0,$colorTransparent);
imagecolortransparent($new_img, $colorTransparent);
}
else
{
$new_img = imagecreatetruecolor($neww,$newh);
}

// Copy and resize image
imagecopyresampled($new_img,$source_img,0,0,0,0,$neww,$newh,$size[0],$size[1]);

 Respond  
Hawkee   -  May 11, 2006

Actually, it might be more complicated than that. It seems imagecreatetruecolor is the way to go, but there has to be a way to retain the transparency.

 Respond  
Hawkee   -  May 11, 2006

tye, I think it\'s better to use imagecreate() rather than imagecreatetruecolor() because I had a couple cases where a gif with a transparent background was converted to a gif with a black background.

 Respond  
F*U*R*B*Y*   -  Apr 14, 2006

very nice, gave you an 8

 Respond  
tye   -  Apr 21, 2005

I updated the snippet to support GIFs and fix a few bugs. The new code has more error checking and more comments.

 Respond  
tye   -  Apr 21, 2005

I\'ve written a better version of this snippet since I uploaded it. I\'ll post that soon. This one seems to have a few problems.

 Respond  
Hawkee   -  Apr 21, 2005

I figured it out. You don\'t consider if maxx == 0 or maxy == 0 in either of your cases. I\'m sure there\'s a better way to organize this code.

 Respond  
Hawkee   -  Apr 21, 2005

There\'s a problem for images that are taller than they are wide. I think you\'re missing an else statement there. Also when you set maxx, but you don\'t set maxy on images of this type, they aren\'t restricted to maxx. It tries to use the maxy value which is 0. I\'m not sure how to fix this.

 Respond  
Hawkee   -  Apr 19, 2005

tye, I found a bug in your code. I\'m not sure if you meant to use $ImageFunc2 at the end or not, but it\'s not used at all. Also you set $ext to .jpg in your if conditiional. It should be ==

 Respond  
Hawkee   -  Apr 19, 2005

tye, looks like PHP supports GIF\'s now after GD version 2.0.28

 Respond  
log2   -  Mar 11, 2005

it could use a bit more comments but i still gave you a 7 :D it\'s good and very usefull

 Respond  
Hawkee   -  Mar 10, 2005

Awesome tye, this is very useful in a lot of different ways.

 Respond  
Are you sure you want to unfollow this person?
Are you sure you want to delete this?
Click "Unsubscribe" to stop receiving notices pertaining to this post.
Click "Subscribe" to resume notices pertaining to this post.