Photo Index Generator - PIG

This page is in English on purpose. Sorry if you can't read it but I'll not translate it.

PIG is a shell script that makes a photo index from a group of JPEG images. It uses netpbm as well as a pasteup program of my own breed.

What PIG does

Given a set of images, the script:

  1. make miniatures (or thumbnails) properly oriented to fit the index image;
  2. arrange the miniatures on the index image;
  3. label them;
  4. write documentational info (date, page number, user given data) on the index image;
  5. convert the resulting image into TIFF.

I wrote a first version based solely on netpbm, but I soon realised that it was far too slow due to the way pnmpaste works: it reads the canvas, paste one image on it and produce the modified canvas on stdout. So if you have n images to paste the canvas file is rewritten to disk 2n+1 times (each miniature image, its caption, and the page label).

So I wrote my own pasteup program, mapping the canvas onto memory instead of traditional read/write. It proved to be rocket fast compared to pnmpaste. I named it ppmpasteup, and made it available as a separate unit, for I believe it may be useful outside the photoindex script.


This software and its documentation, including this page, is copyright ©2005 by Danton Nunes and is protected by Brazilian and International intellectual property laws.

This software (photoindex and ppmpasteup) is licenced according to GPL version 2, taking as authoritative the Brazilian-Portuguese version. Disputes, should they happen, are to be settled at a Brazilian court.

The author does not guarantee that these programs are correct or fit to any purpose (well, I know it works, but do not blame me if it misbehaves on your environment). Check paragraphs 11 and 12 of GPL.


  1. A decent Unix environment (Linux, *BSD, may work on MacOS);
  2. C compiler;
  3. Bourne-Again Shell (/bin/bash);
  4. An up-to-date netpbm package, including headers and libnetpbm;
  5. JPEG utilities: djpeg, rdjpgcom.

How to install

  1. Download. All you need is here.
  2. Unpack.
    tar xzf pig-x.xx.tar.gz
  3. Compile ppmpasteup:
    cd pig-x.xx
    gcc -o ppmpasteup ppmpasteup.c -lnetpbm
  4. Place things where they belong:
    cp ppmpasteup photoindex /usr/local/bin
    (or elsewhere if you wish). This must be done by root.
  5. Optionally strip ppmpasteup (also by root)
    strip /usr/local/bin/ppmpasteup

and, voila! There is no Makefile or ./configure. It would be like killing a mosquito with a machine gun to have them, and I like neither mosquitoes nor guns, be machine or not.



photoindex [options] image ...

Options are:

-t title
text to be pasted on index label (default: blank)
-o file
output file name (default: index)
-d density
pixel density in dpi (dots per inch) (default: 300)
-w width
paper width (default: 12cm)
-h height
paper height (default: 12cm)
-s space
spacing between neighbour images (default: 1mm)
-r rows
number of rows (default: 8)
-c cols
number of columns (default: 6)
-v level
verbosity level: 0=silent, 1=page progress, 2=file progress, 3=details (default: 0)

Dimensions may be given in cm, mm, in, or px (pixels). If given, the density option must come before any dimension option.

The defaults are for a 12cm×12cm index, good for a CDROM cover.

dimensions and disposition of elements

If one of the image names points to no file, an empty file or a non-JPEG/JFIF file, an error message is pasted en lieu of the miniature image.


ppmpasteup canvas image1 x1 y1 [ image2 x2 y2 ... ]

PPM file name where images will be pasted. A wise idea is to create it with ppmmake.
file containing PPM image to be pasted onto canvas. A - stands for standard input.
coordinates in pixels, from the top left corner of canvas, where the top left corner of the pasted image will be. Negative values refer to the canvas bottom right corner.

The images must fit the canvas. ppmpasteup checks for boundaries and aborts if an image overflows the canvas. Nevertheless, to make the program faster, no check is done on the right border of the canvas. If an image overflows the canvas right border it will be wrapped to the left. This may lead to very funny results.

Images may be pumped to ppmpasteup through standard input. Many images may be concatenated, as in the example:

{ djpeg img1.jpg; cat img2.ppm; } |
        ppmpasteup page.ppm - 0 0 - 100 200

where img1.jpg will be pasted just on the top left corner of page.ppm and img2.ppm at 100 pixels from the left border and 200 pixels down from the top.

This program produces nothing at standard output. The canvas file contents is modified.

The images must be real PPM. I could have used libnetpbm to read images so any P*M format could be acceptable but this would have slowed the beast down. In order to paste a PBM you have to promote it to PPM before submitting it to ppmpasteup. A useful example is how to put captions or text using pbmtext:

pbmtext 'a sunset scene' | pnmdepth 255 |
pgmtoppm 'rgbi:1/1/1' | ppmpasteup canvas.ppm - 15 -120

will place the caption "a sunset scene" at coordinates 15,120 pixels from the bottom left corner of the image in canvas.ppm.

(Un)Frequently Asked Questions

  1. Does it run on Windows?

    I don't know, and I don't care.

  2. Is there a graphical interface?

    No, but feel free to write one, for I won't.

  3. Is there a man page?

    None, so far.

  4. Why JPEG images only? Can't the script deal with other formats?

    Because when I did it most of my images were JPEG. Maybe in a future version I replace anytopnm for cjpeg, but I still don't know how to handle error conditions properly. Anyway, this is in the todo list.


If you find this software useful, make any modification, port to non-Linux environments, or just want to make suggestions or critics, please feel free do drop me a message.