Colourise a PGM Image with pgmtoppm
pgmtoppm turns a flat greyscale PGM into a colour PPM, with the black and white endpoints under your control. Allow about ten minutes if Netpbm is already installed, and watch the maxval or you lose tonal detail along the way.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1.
- You need: a readable PGM file and the commands
pgmtoppm,pnmfile, and, for the depth example,pamdepth. - It will not touch: the input image. These are ordinary user commands and nothing here needs
sudo.
1. Check the installed command
Confirm which executable will run and record its Netpbm version. This catches a surprisingly common distraction: reading documentation for one installation while a different binary is first in your PATH.
$ command -v pgmtoppm
/usr/bin/pgmtoppm
$ pgmtoppm -version 2>&1 | head -4
pgmtoppm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pgmtoppm: Built from source dated 2024-03-31 09:09:47
pgmtoppm: Built by Debian
pgmtoppm: BSD defined
Checkpoint
If command -v finds nothing, install Netpbm through your normal package-management process before continuing. Do not solve a missing command by running the converter as root.
2. Convert with explicit endpoint colours
pgmtoppm reads a PGM and writes a PPM to standard output. The -black value replaces input black, -white replaces input white, and intermediate grey values are interpolated between those colours. Redirect the output to a new name first so the source remains available:
$ pgmtoppm -black=navy -white=white /path/to/input.pgm > /path/to/colourised.ppm
$ pnmfile /path/to/colourised.ppm
/path/to/colourised.ppm: PPM raw, 1024 by 768 maxval 255
The dimensions in the sample output are illustrative. Your file should report the input dimensions, a PPM format, and a maxval matching the input unless you use -map. A non-zero exit status means the conversion failed, so check the input path and permissions before you go looking at the image.
Warning
Do not use a destination that holds the only copy of a valuable image. Shell redirection truncates an existing file before pgmtoppm starts. If you must replace an existing output, use a temporary destination and move it into place only after verification:
$ pgmtoppm -black=navy -white=white /path/to/input.pgm > /path/to/colourised.ppm.new
$ pnmfile /path/to/colourised.ppm.new
$ mv /path/to/colourised.ppm.new /path/to/colourised.ppm
Recovery
The final mv is the deliberate state-changing step, so remove the .new file first if the check fails. If the move has already happened, restore the previous file from your backup or snapshot; pgmtoppm supplies no undo operation.
3. Understand the maxval trap
PGM stores samples from zero to its declared maxval. Without -map, the PPM that pgmtoppm produces keeps that maxval, so a low-depth source cannot express many subtle output colours, even when you ask for a vivid endpoint colour.
This one-bit PGM, for example, produces a PPM whose maxval is still 1:
$ printf 'P2\n2 1\n1\n0 1\n' | pgmtoppm red | pnmfile
stdin: PPM raw, 2 by 1 maxval 1
If the source needs more tonal resolution, raise its depth in the pipeline before colourising it. This keeps the same two pixels but gives the output 256 representable levels:
$ printf 'P2\n2 1\n1\n0 1\n' | pamdepth 255 | pgmtoppm red | pnmfile
stdin: PPM raw, 2 by 1 maxval 255
Use a depth suitable for the image and the next tool. The manual also documents pamdepth 16; 255 is a straightforward general choice. This changes only the streamed copy, not the original file.
4. Use the historical shorthand when it helps
The explicit options are easiest to review, but the command also accepts a colour argument: a single colour sets the white endpoint and leaves black at its default, while a pair separated by a hyphen sets both endpoints:
$ pgmtoppm black-red /path/to/input.pgm > /path/to/red-scale.ppm
$ pnmfile /path/to/red-scale.ppm
/path/to/red-scale.ppm: PPM raw, 1024 by 768 maxval 255
Keep the explicit form in scripts when a colour name or specification might contain punctuation. Netpbm accepts colour specifications understood by its colour parser; simple names such as navy, red, and white are easier to audit than an unexplained numeric string. The installed manual also permits a space instead of =, and accepts double hyphens, but full spelling with = reads clearer:
$ pgmtoppm --black navy --white white /path/to/input.pgm > /path/to/colourised.ppm
5. Apply a multi-colour map when two endpoints are not enough
Use -map when the scale needs several deliberate colours. The map is a PPM file: its pixels are used in order, with black mapped to the first colour, white to the last, and values between them spread across the sequence. Its maxval becomes the output maxval.
$ pgmtoppm -map=/path/to/heatmap.ppm /path/to/input.pgm > /path/to/heatmap.ppm.out
$ pnmfile /path/to/heatmap.ppm.out
/path/to/heatmap.ppm.out: PPM raw, 1024 by 768 maxval 255
Do not combine -map with -black or -white. If you need exact per-level assignments rather than interpolation across a map, use pamlookup and build its index file according to that command's documentation.
6. Diagnose the result before handing it on
Run pnmfile after every conversion that matters. Confirm the file is non-empty, the dimensions match the source, the format is PPM, and the maxval is high enough for the colours you chose. If a downstream program only needs to read the image as PPM, remember that Netpbm PPM readers can generally accept PGM directly; for a plain format conversion with no colourisation, ppmtoppm is the more direct tool.
- Result unexpectedly flat or nearly black? Check the source maxval first. A maxval of 1 or another small value can quantise away intermediate colours.
- Command rejects a colour? Try a simple named colour such as
red, then consult the installedpgmtoppm(1)and colour-parser documentation for the exact specification you want. - Cannot open the input? Check with
ls -landtest -rbefore reaching for elevated privileges, which should not be your first response.
Done means
- Confirmed the install.
pgmtoppmis the expected Netpbm installation and its version is known. - Kept the source safe. The PGM remains untouched and the destination is a verified PPM.
- Chose colours deliberately. Black and white endpoint colours are explicit, or the shorthand choice is understood.
- Checked the maxval. The output maxval is high enough to preserve the intended tonal detail.
- Used a map only when needed. A map file is used only for a genuine multi-colour scale, without endpoint options.
- Stayed unprivileged. No command ran as root, and an existing output was not overwritten by accident.