Thumbnail page generation tools

This software is not being maintained any more. It can still be used in modern GNU/Linux systems, but there are many other more advanced free tools available.

Latest news

02.07.2003. Fixed the file name extension check in all scripts to accept endings written in capital letters. Now they accept .jpg, .JPG, .jpeg and .JPEG. Thanks to Simo Neuvonen for finding this bug.

14.04.2003. Fixed to correctly handle filenames which contain spaces.

14.02.2003. New version 1.1 with several enhancements:

Bug fixes: parsing image size with recent ImageMagick fixed, ensures that thumbnail sizes are integers (floating point values rounded)


When I bought a digital camera in 1999 I wanted to generate simple web pages with thumbnail images to make my photos easily accessible. I wasn't happy with the existing solutions I could find, so I wrote my own. The tools are a few scripts written in Perl, designed for my own use but should be relatively easy to modify to suit other needs. The scripts take advantage of a few command line image manipulation tools that are quite popular in the Unix/Linux world.

Example output

System requirements

You need to have at least the following packages installed:

I don't know what are the oldest versions that will work, but any release from the last five years or so should do fine. Most GNU/Linux distributions install these tools by default so you are probably ready to go. For some optional functions these programs are also necessary:

I have used the scripts mostly on Debian GNU/Linux, but they should work with other GNU/Linux distributions and Unix systems too. Both Perl and ImageMagick are also available for Windows, but I haven't tried them and some of the code might be Unix-specific. If you have tested the scripts in a Windows environment, I would be happy to hear about the results.

By default, the image scaling is done using utilities cjpeg, djpeg and pnmscale (found in libjpeg-progs and netpbm packages in Debian GNU/Linux, libjpeg and libgr-progs in Red Hat). If they are not found, the script does the same thing automatically with ImageMagick's convert, which works fine but is considerably slower.

Download and installation

Download the file thumbnailtools.tar.gz. It contains the following scripts:

You don't have to be root on the machine, I often use a directory named bin under my normal user account. Then make sure that they have the execute permission set, the path to perl executable on the first line is correct and add the directory to your shell path.

If you don't understand the terms used in the previous paragraph, take a look at some book or tutorial on the web that explains the basics of Unix. The UNIX Tutorial for Beginners is one of the many possibilities.


All the scripts currently handle only jpeg format images, there's a simple check that the filenames end in either .jpg, .JPG, .jpeg or .JPEG. Extending the functionality to other formats should be trivial in most cases, as ImageMagick supports a wide variety of them, but I thought that restrictions are better than unpredictable output.


Thumbgenerator is the main script and is invoked from the command line with the following syntax: [OPTIONS] [IMAGEFILES]

The script produces a thumbnail image for each file given as a parameter, and a html file (index.html by default). The thumbnails are named using the keyword small, for instance the thumbnail file for image picture.jpg will be named picture_small.jpg.

The script accepts the following options:

-c filename Read image captions from a file given as argument. Each line should contain one image file name, followed by one or more tab characters and the caption text. Empty lines and lines beginning with "#" character are treated as comments and ignored. Caption file example.
Default: no caption file.
-d dividers The scaling factors / number of pixels for thumbnail sizes. This is a list of values separated by semicolons ";" - if you supply more than one value several versions of each image will be generated. Each value can be one of the following types:
  • plain number (floating point ok) - divide the original size with this value
  • a number preceded by X (for example X256) - create thumbnails with width fixed to given number of pixels
  • a number preceded by Y (for example Y256) - create thumbnails with height fixed to given number of pixels
  • a number preceded by L (for example L256) - create thumbnails with the longer of the two edges fixed to given number of pixels
Example: "L256;L800" - create thumbnails with height and width not exceeding 256 pixels and a set of medium size images with height and width not exceeding 800 pixels. The aspect ratio of original images is always maintained.
Default: L256
-e endings A list of endings (suffixes) for naming the generated thumbnails. There must be at least as many endings as scaling factors given using the -d option. The necessary number from the beginning of the list are used. By default, image files matching these suffixes are also skipped when running the script, to avoid generating new thumbnails from already generated thumbnail images (e.g. image_small_small.jpg from image_small.jpg).
Default: "_small;_medium;_large".
-m columns If > 0, use multicolumn mode: images organized in a table with "columns" columns.
Default: multicolumn mode off
-n If set, just regenerate html (no thumbnail generation). Fast, useful if you just want to change the html layout.
-o name Output html file name.
Default: index.html
-q quality Output jpeg quality.
Default: 75%
-s subject Page title.
Default: "Some pictures"

You must supply at least one image file, all the other parameters are optional. See the section Examples and source code for more information.

There are also some other parameters in the beginning of the source code which are not adjustable from command line. The idea is that the user can modify the defaults and the html code directly in the source code to produce pages that suit his or her preferences. I have tried to keep the code easily understandable, but that goal may have suffered a bit when adding new features. Don't hesitate to ask me if you have problems.


Rotate_images can be used to turn images clockwise a variable number of degrees, handy if you have taken both horizontal and vertical photos with a digital camera, for instance. It also saves the original versions with the suffix _orig.jpg to keep them available for future image editing needs.

If the original version exists already, it is not replaced but used as the source for rotating.


Available options:

-a degrees Amount to rotate (clockwise), either the keyword "auto" or a number, for example 90 to rotate 90 degrees.
Default: auto.
-q quality Output jpeg quality, either the keyword "lossless" or a number, for example 75 to produce "JPEG 75%" quality.
Default: lossless

For lossless rotation, you will need to have jpegtran (or jpegtran-mmx) installed. Jpegtran is able to rotate jpeg images by just reordering the image blocks, thus without decompressing and recompressing the image at all during the process. Therefore there is no degradation in quality - you will most probably want to use that. For backwards compatibility, older behaviour of rotating using the ImageMagick convert tool (which does decompression and recompression) has also been preserved - give a number as the quality value to use that.

Usually you need to specify the amount of rotation manually. The "auto" option is handy if you have a digital camera with an orientation sensor which marks the orientation in the EXIF header of the JPEG file. For example my camera (Canon Powershot S45) does that, but for some reason does not rotate the images itself. Using the "auto" option I can let the script go through all the images and check from the header which ones need to be rotated. The jhead tool needs to be installed for this functionality.
Note! Currently the script does not write the modified orientation in the header of the new image but leaves the header untouched. This can be considered a bug...


Compress_images can be used to compress a group of images to a certain quality (for example to put them on display on the web) while still preserving the original ones for future use. This script is actually only a simple wrapper for the convert program in the ImageMagick package.


Available options:

-q quality Output jpeg quality.
Default: 75 (produces "JPEG 75%" quality images)

There are some subtle issues concerning the image naming scheme. To avoid losing quality with successive compressions and to facilitate parallel use with the rotate_images script, the image is skipped by default if the original version (extension _orig) is found. This can be adjusted in the beginning of the source file.


A simple session in a directory with three pictures might look like this:

[~/pictures/]$ ls
image1.jpg  image2.jpg  image3.jpg 
[~/pictures/]$ *.jpg
Processing image image1.jpg
Processing image image2.jpg
Processing image image3.jpg
[~/pictures/]$ ls
image1.jpg        image2.jpg        image3.jpg        index.html
image1_small.jpg  image2_small.jpg  image3_small.jpg                

Here's a bit more complicated example that shows how I normally use the scripts:

1. Generate a simple page to view the images with a web browser:

[~/pictures/]$ *.jpg
Processing image image1.jpg
Processing image image2.jpg
Processing image image3.jpg
Processing image image99.jpg

2. Rotate images that are not in the right orientation:

[~/pictures/]$ -a 90 image2.jpg image3[578].jpg
Processing image image2.jpg
Processing image image35.jpg
Processing image image37.jpg
Processing image image38.jpg

Knowing how to use shell wildcards is often useful. For instance the previous command rotates pictures image2.jpg, image35.jpg, image37.jpg and image38.jpg, but not image3.jpg or image36.jpg.

If the orientation is already marked in EXIF headers, you can just skip the amount and give "*.jpg" to process all the files.

If we used lossless rotation (the default), we can probably safely remove the originals:

[~/pictures/]$ rm *_orig.jpg

3. Compress the images choosing a suitable quality for web pages (e.g. 60%):

[~/pictures/]$ -q 60 image?.jpg image??.jpg
Processing image image1.jpg
Processing image image2.jpg
Processing image image3.jpg
Processing image image99.jpg

Note that after generating the thumbnails, the directory contains also the files image1_small.jpg, image2_small.jpg etc. To avoid making compressed versions of all of them, the list of image files is given as image?.jpg image??.jpg and not *.jpg. In most shells, the asterisk means "any string" (including zero lenght), the question mark is "any character" (exactly one).

Another subtle thing in the operation is that the script skips file.jpg by default if file_orig.jpg exists too. This is to avoid either replacing and recompressing images that have been generated with the rotate_images script. The behaviour can be changed by modifying the value of NO_COMPRESS_IF_ORIGINAL in the beginning of the script.

4. Regenerate the page with desired thumbnail quality, a set of medium sized pictures and links to both them and high resolution versions, plus a title:

[~/pictures/]$ -d "L256;L640" -q 60 -s "Trip to Chamonix" *.jpg
index.html exists, overwrite (y/n)? y
Processing image image1.jpg
Skipping image image1_orig.jpg
Skipping image image1_small.jpg
Processing image image2.jpg
Processing image image99.jpg
Skipping image image99_orig.jpg
Skipping image image99_small.jpg

The generated page (see example output) contains the thumbnails, links to the bigger versions of the pictures and basic information about their date and size. You can easily write comments next to the pictures directly in the html file or a separate caption file (example)

5. Regenerate the page including the captions. Multicolumn mode "-m 3" makes a layout with three columns. Now there's no need to reprocess the actual images, generating just the html page is enough and saves time (-n option):

[~/pictures/]$ -d "L256;L640" -n -m 3 -c captions.txt -s "Trip to Chamonix" *.jpg

You are expected to change the html code in the script to get the layout you like. You will at least want to replace the text Unknown Author by your name, and maybe also change the conditions for copying. The default text explicitly permits redistribution as I prefer to do so, but using this script naturally doesn't require you to do the same.


The jhead utility has many very handy options if you are processing images taken with a (relatively modern) digital camera. It can for example read exposure information from the EXIF header, set the file modification date according to the date stored in the header, and reduce file size by removing unnecessary thumbnails many cameras embed inside the header.

Nowadays there are also many other thumbnail generator / digital photo album management packages for Linux/Unix-systems, I plan to evaluate them some day.


20.02.2004. Moved the scripts to a .tar.gz file to avoid web server error (my current hosting provider server doesn't seem to like .pl files).

02.07.2003. Fixed the file name extension check in all scripts to accept endings written in capital letters. Now they accept .jpg, .JPG, .jpeg and .JPEG. Thanks to Simo Neuvonen for finding this bug.

14.04.2003. Fixed to correctly handle filenames which contain spaces.

14.02.2003. New version 1.1 of and with several new features and a couple of bug fixes. (Especially one that caused to fail when parsing the image size with recent versions of ImageMagick).

If you want a more simple script to start with, you can also download the old versions without new features, just bugfixes applied: thumbnailtools-old.tar.gz, contains

19.10.2001. Fixed a small bug in command line utilities detection code (

29.11.2000. First published version


The program, including the scripts and this document, is free software, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

<< Back to software index

Arto Teräs <> - last update 03.07.2016.