Home / Alt manpages / pnmindex(1)

  • pnmindex(1)
  • User command
  • linux

Build a Contact Sheet from PNM Images with pnmindex

pnmindex builds one PPM contact sheet of labelled thumbnails from a folder of PNM images. The examples use Netpbm 11.5.2 from package version 2:11.05.02-1.1build1, and write the generated image to a new file. Allow about fifteen minutes if your input files are ready. You need a shell, the netpbm package, readable PNM images, and enough temporary and output space.

Checkpoint

The basic workflow is input PNM files, pnmindex on standard output, and shell redirection into a PNM output file. The command does not edit the input images and does not need elevated privileges.

1. Confirm the installed command

Check which executable will run and record the Netpbm build:

$ command -v pnmindex
/usr/bin/pnmindex
$ pnmindex --version
pnmindex: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pnmindex: Built from source dated 2024-03-31 09:09:47
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

The version line is diagnostic output from this installation. It is useful when comparing results with another machine, because thumbnail and colour-processing details can depend on the Netpbm build.

2. Check the inputs and choose their order

pnmindex accepts one or more PNM files. It makes a thumbnail for each file and labels it. A shell glob is convenient, but its expansion order becomes the order in the contact sheet. Inspect the files before running the generator:

$ printf '%s\n' photos/*.ppm
photos/01-front.ppm
photos/02-side.ppm
photos/03-back.ppm
$ file photos/*.ppm
photos/01-front.ppm: Netpbm image data, size = 1600 x 1200, rawbits, pixmap
photos/02-side.ppm: Netpbm image data, size = 1600 x 1200, rawbits, pixmap
photos/03-back.ppm: Netpbm image data, size = 1600 x 1200, rawbits, pixmap

Replace photos/*.ppm with a path that matches your files. Do not use a broad glob such as * unless you have checked that every matched file is a supported PNM image. A shell error such as an unmatched pattern can also leave the literal pattern in the argument list, so check the expanded list first.

3. Create the first contact sheet

Run the default layout and redirect standard output to a new file:

$ pnmindex photos/*.ppm > contact-sheet.ppm
$ file contact-sheet.ppm
contact-sheet.ppm: Netpbm image data, size = 4800 x 500, rawbits, pixmap
$ test -s contact-sheet.ppm && printf 'contact sheet is non-empty\n'
contact sheet is non-empty

The defaults are a 100 by 100 pixel thumbnail box and six thumbnails across each row. An input smaller than the box is not enlarged. The output is a PNM image, normally a PPM when the inputs include colour data, so use a viewer or another Netpbm tool that understands PNM to inspect it.

The dimensions in the example are illustrative. Your output size depends on the input aspect ratios, labels, title, and number of rows. If the command fails, read its diagnostic before opening the output. A shell redirection can create an empty destination before the program reports an error, so do not treat the existence of the file alone as success.

4. Set thumbnail size, columns, and title

For a more compact sheet, set the maximum thumbnail box and the number of thumbnails per row. Add an ASCII title when the image needs context:

$ pnmindex -size=160 -across=4 -title='March inspection' \
    photos/*.ppm > march-contact-sheet.ppm
$ file march-contact-sheet.ppm
march-contact-sheet.ppm: Netpbm image data, size = 680 x 620, rawbits, pixmap

-size=160 means each image is scaled down to fit inside a 160 by 160 pixel square without changing its aspect ratio. It is not a forced crop or exact output size. -across=4 puts four thumbnails in each row. Both values must be at least 1. The title is optional, and its value must be ASCII; characters outside ASCII are not rendered by this program.

The option syntax also accepts a space instead of an equals sign, and two hyphens instead of one. For example, --size 160 is equivalent to -size=160. Keeping the equals form in scripts makes the option and its value easier to spot.

5. Choose the background and colour behaviour

By default, padding and label backgrounds are white with black lettering. Use -black to reverse that presentation:

$ pnmindex -size=160 -across=4 -black -title='March inspection' \
    photos/*.ppm > march-contact-sheet-dark.ppm

If any input is PPM, the default processing quantises colours to a maximum of 256 colours in the overall image. The palette-limit option changes that maximum:

$ pnmindex -size=160 -across=4 -colors=128 \
    photos/*.ppm > march-contact-sheet-128.ppm

Colour quantisation is applied per thumbnail, per row, and then to the complete output. Lowering the limit can reduce colour variety and file size, but it may make gradients or photographs look rougher. The palette limit has no effect with -noquant, or when none of the inputs is PPM. Use -noquant when preserving the input colours matters more than limiting the palette:

$ pnmindex -noquant -size=160 -across=4 \
    photos/*.ppm > march-contact-sheet-full-colour.ppm

-quant is accepted but selects the default quantising behaviour, so it is not a way to request higher quality. If the result looks unexpectedly limited, check for an inherited palette setting in a script and decide explicitly between the default and -noquant.

6. Account for temporary files and recover safely

pnmindex can create large temporary files. It uses /tmp by default; set TMPDIR to a filesystem with sufficient space before processing a large set:

$ mkdir -p "$HOME/tmp/netpbm"
$ TMPDIR="$HOME/tmp/netpbm" pnmindex -size=200 -across=5 \
    photos/*.ppm > contact-sheet.ppm
$ test -s contact-sheet.ppm && printf 'output verified\n'
output verified

The directory creation changes your home directory, but it does not require root. Check its free space first if the inputs are large. Do not point TMPDIR at a shared directory with unsafe permissions when processing private images.

If you need to replace an existing contact sheet, write to a new temporary output in the same directory, verify it, then move it over the old file. The move is the destructive step: it removes the previous version. Keep a backup or use a distinct filename when the old sheet is valuable. To undo an accidental replacement, restore that backup. No undo is needed for the examples above because they create new output names.

7. Diagnose the common failures

  • Unknown or unreadable input: run file on every expanded argument and check its path and permissions. Do not run the command as root to hide an ordinary file access problem.
  • Bad layout value: -size and -across must be at least 1. Correct the command rather than relying on a fallback.
  • Missing title characters: -title only renders ASCII. Use an ASCII replacement if the label must appear in the image.
  • Unexpected colours: remember that PPM input triggers the default quantisation and that the palette limit is a maximum, not a promise that every colour will remain.
  • Empty or truncated output: check the command's exit status and use test -s plus file. Preserve the last known-good sheet until the new one has passed those checks.

Done means

  • The installed Netpbm version and the input file list were checked.
  • A new, non-empty PNM contact sheet was created without modifying the inputs.
  • Thumbnail size, row width, title, background, and quantisation choices are explicit where they matter.
  • The output was checked with file and its exit status was considered.
  • Temporary space is available, and an existing sheet will not be overwritten before its replacement is verified.