Creating An Index Image - Page 22
December 18, 2001
|
In this article, we will learn how to use the GD library to
create an index image that contains thumbnails of images in a
given directory.
|
Creating An Index Image
I have a digital camera that I use quite a bit to take pictures
at conferences, family events, and vacations. It's convenient to
have a single image that has thumbnails of all of the images that
I take, similar to the index images that you sometimes get when
you have 35mm film developed. In a
previous article, we learned how to create a single thumbnail
image. We will leverage that example to create an index image. An
index image contains a group of thumbnails for an image set. For
this example, an image set will be the images that exist in a
given directory. For this article, I've pilfered a set of
pictures that I took at Seaworld in Miami, Florida. You can see
the results here.
One of the nuisances of the GD module has been its lack of
support for the GIF image format. Fortunately, the most recent
version of the Perl GD library has been patched to support GIF
again. Thank you Lincoln Stein (author of the Perl GD library)!
When I first developed this example though, support was not
available. Fortunately, all of my images are in JPEG format, so
this wasn't an issue, but there are certainly many GIF images out
there.
Searching For Images In A Directory
The first thing we need to do is to get our list of images that
we want to include in the index image. We can do this by opening
a directory handle with the opendir() function and
filtering for .JPG files with the readdir,
grep, and map.
opendir(DIR,$dir) || die "Cannot open directory $dir: $!\n";
my @images = grep -f, grep /\.jpg$/i, map "$dir/$_", readdir DIR;
closedir(DIR);
The readdir function returns an array containing the
list of files in the directory in the given directory handle
(DIR). This list will not only include files that
are JPEG images, but it also returns subdirectories. We can
filter the results that are returned before the list is assigned
to our @images array by applying a number of
filters, separated by commas, with the grep command.
grep -f filters the list with the -f switch, which
will only return files that are indeed files (not directories).
grep /\.jpg$/i filters for all files that end with a
.jpg extension. This gives us a complete listing of all JPEG
files in the directory. However, we need to take one additional
step.
Because we need to open each JPEG file in the directory, we
should map the name of the directory onto the file names so that
the program knows where to fetch the files from. This is done
with map "$dir/$_", which appends the directory
name specified in the $dir variable, followed by a
slash, on the each file name.
Setting Borders, Spacing, And Thumbnail Sizes
The next thing to think about concerns size and spacing of the
borders and thumbnails. We need to set a maximum width and height
that each thumbnail must fit into. We don't actually want to
simply resize the image to the thumbnail specifications, rather
we want to resize the image to fit within the dimensions while
also maintaining the image proportions. I decided that the
thumbnails should fit within a 100 x 100 pixel size.
Another thing to think about is the number of thumbnails you'd
like per row. This largely depends on your personal preference
and the size of the thumbnail dimensions that you select. I've
decided that five images across for each row works out nicely for
my monitor.
We also need to decide how many pixels we want between thumbnails
and at the borders. I've decided on 20 pixels between images in a
row and 40 pixels between rows. We need more space in between
rows so that we can notate each image with its filename. We also
need to leave a space at the top of the image so that we can add
a title.
I've created a number of variables for the settings I just
described:
$imagesPerLine — the number of
thumbnails to display in each row.
$titleBorder — the number of pixels to
leave at the top of the image for a title.
$vBorder — the number of pixels between
thumbnails in a row.
$hBorder — the number of pixels between
rows
$maxThumbnailW — the maximum width of a
thumbnail
$maxThumbnailH — the maximum height of a
thumbnail
Calculating The Index Image Size
Now we need to calculate the size of the index image given the
list of JPEG images that we filtered out previously. The first
thing we can do is figure out how many rows we'll have by
dividing the number of images in the @images array
by the number of images to display on each row contained in the
$imagesPerLine variable.
my $rows = ceil(scalar(@images) /
$imagesPerLine)
Now we can calculate the width of the index images by multiplying
the maximum number of images per row by the maximum thumbnail
width and adding to that the number of pixels that will be used
for spaces in between the images and at the edge of the index
image. We can calculate that spacing by multiplying the
horizontal border by the number of images per line, minus 1, plus
two more borders for the edge of the index image.
my $indexWidth = ($maxThumbnailW *
$imagesPerLine) + ($hBorder * ($imagesPerLine - 1 +
2));
Likewise, we can determine the height of the index image by
multiplying the number of rows by the maximum thumbnail height,
and adding to that the spacing that will be drawn between rows,
adding to that the space at the top of the index image that will
be used for the title.
my $indexHeight = ($maxThumbnailH * $rows) +
($vBorder * ($rows - 1 + 2) + $titleBorder);
Drawing a pie chart with GD::Graph::pie - Page 21
Weaving Magic With Regular Expressions
Create An Empty Index Image And Draw The Title - Page 23
|