Home : Webmonkey : Code : Perl Thumbnail Creator

introduction

If you have chat-friend access to this site, you will have noticed that I have a large collection of pics, spanning many years. This would normally make the generation of thumbnail pictures an onerous task.

I think that laziness is half the reason that I'm a programmer. There was no way that I was going to hand create so many thumbnail images. I made the computer do it

example

code

#!/usr/bin/perl
use Image::Magick;

@inDirectories = (
  "/home/stormy/Documents/people/family"
  ,"/home/stormy/Documents/art"
  ,"/home/stormy/Documents/me/1975-1997"
  ,"/home/stormy/Documents/me/1998"
  ,"/home/stormy/Documents/me/1999"
  ,"/home/stormy/Documents/me/2000"
  ,"/home/stormy/Documents/me/2001"
  ,"/home/stormy/Documents/me/2002"
  ,"/home/stormy/Documents/me/2003"
  ,"/home/stormy/Documents/me/2004"
  ,"/home/stormy/Documents/me/2005"
);
$outDir = "thumbs";
$grabFrom = "web";

foreach $directory (@inDirectories){
  $directory .= "/$grabFrom";
  opendir(DIR,"$directory") || warn "Cant open directory $directory: $!";
  @files=readdir(DIR);
  closedir(DIR);
  foreach $file (@files){
    if($file=~/jpg$/ || $file=~/gif$/ || $file=~/jpeg$/){
      &makeThumb($directory,$file);
    }
  }
}

sub makeThumb{
  ($path,$file)=($_[0],$_[1]);
  ($name,$ext)=$file=~/^(.+)\.([^\.]+)$/;
  print "$path/file=$file\n";
  unless($name eq ""){
    $width=100;$height=100;$offset="10";

    # import, bleach and resize for shadow image
    # image proportions are kept in the resize, so
    # work out the diff in order to centre later.
    $shadow = Image::Magick->new;
    $shadow->Read("$path/$name.$ext");
    $tw=$width-2;$th=$height-2;
    $shadow->Resize(geometry=>$tw."x".$th);
    $shadow->Border(geometry=>'1x1', fill=>'#888888');
    $shadow->Gamma(3);

    ($w, $h) = $shadow->Get('width','height');
    $x=($w<$width)?int(($width-$w)/2)+1:1;
    $y=($h<$height)?int(($height-$h)/2)+1:1;

    # import and resize image for thumbnail
    $image = Image::Magick->new;
    $image->Read("$path/$name.$ext");
    $image->Resize(geometry=>$tw."x".$th);
    $image->Border(geometry=>'1x1', fill=>'#c0c0c0');

    # stick the shadow, then the thumbnail onto large
    # canvass. Crop back to desired images, sheer it, then
    # fix the size again.
    $prebase = Image::Magick->new;
    $prebase->Set(size=>'500x500');
    $prebase->ReadImage('xc:white');
    $prebase->Composite(image=>$shadow,compose=>"over",x=>$offset+$x,y=>1+$y);
    $prebase->Composite(image=>$image,compose=>"over",x=>1+$x,y=>$offset+$y);
    $gw=$width+$offset;$gh=$width+$offset;
    $prebase->Crop(geometry=>$gw."x".$gh);
    $prebase->Shear('10x4');
    $prebase->Resize(geometry=>$width."x".$height);

    # after sheering, we're a couple of pixels off being
    # square, so we past onto a square canvas.
    $base = Image::Magick->new;
    $base->Set(size=>$width."x".$height);
    $base->ReadImage('xc:white');
    $base->Composite(image=>$prebase,compose=>"over");
    $base->Write("$path/$outDir/$name.jpg");
  }
}

discussion

The first thing I do is give the script a list of directories to look in - but I also tell the script that, as a standard, it should look in a particular subdirectory. In this case, that directory is called "web"

When it looks in these directories, the script has been told to process files that end in .gif, .jpg and .jpeg. When it finds such files, it passes them to the makeThumb subroutine

The thumbnails for this site are pretty fancy. They have a shadow which is actually a faded version of the original and the whole thumbnail is also skewed slightly

The makeThumb routine:

  • imports, resizes and bleaches the picture;
  • imports and resizes the original image;
  • places the bleached image on a fresh canvas;
  • places the unbleached image on top of that;
  • crops the composite image back to a decent size;
  • sheers the composite image to give it that skewed look;
  • fixes the size again;
  • pastes the whole thing onto a correct sized canvas; and
  • saves the thumbnail to the configured "thumbs" directory.

Probably more stuffing around with size than is strictly necessary, but it gets the job done.