Home / Alt manpages / ppmchange(1)

  • ppmchange(1)
  • User command
  • linux

Swap Colours in a PPM with ppmchange

ppmchange swaps chosen colours in a PPM image and writes the verified result without touching the source file. The examples use ppmchange from Netpbm 11.5.2, installed here as package version 2:11.05.02-1.1build1. Allow about ten minutes if the input file is ready.

You need the netpbm package and a writable working directory. This is an unprivileged image operation: do not use sudo unless ordinary file permissions genuinely block access to the input or output directory. The command reads a PPM image and writes the converted image to standard output; shell redirection decides where that lands.

1. Check the Installed Command

Confirm which executable will run and record the package version. These checks change nothing:

$ command -v ppmchange
/usr/bin/ppmchange
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

Netpbm's manual page for this installed command is dated December 2016. The local package version is the reference point for the examples below. If your distribution ships another release, run man ppmchange before putting an option into a script.

2. Replace One Exact Colour

Give one old-colour and new-colour pair, followed by the input file. The input is never edited:

$ ppmchange red blue /path/to/input.ppm > recoloured.ppm

Colour names go through Netpbm's colour parser. Names such as red, blue and black are convenient, while a numeric form the parser accepts is useful when you need an exact shade. Keep the old and new values as separate arguments, and quote a value if your shell builds it from user input.

By default the match is exact: a pixel must have the specified red, green and blue values at the image's own scale. Pixels with other colours stay unchanged unless you set a remainder colour later.

Checkpoint

Check the exit status immediately and inspect the PPM header. PPM output is commonly binary, so do not expect the whole image to be readable with less:

$ printf 'exit status: %s\n' "$?"
exit status: 0
$ file recoloured.ppm
recoloured.ppm: Netpbm image data, size ...

The wording from file varies; a successful check should show a non-empty Netpbm image. For a direct header check:

$ head -c 2 recoloured.ppm
P6

The installed command writes a raw PPM stream with the P6 magic number in this example. Do not treat the output as text or paste its binary bytes into a terminal.

3. Preserve the Old Output While Testing

Shell redirection with > truncates its destination before ppmchange starts, which can destroy a previously useful result if the command then fails. Use a temporary output beside the final file, verify it, and replace the final file only after the check:

$ ppmchange red blue input.ppm > input.ppm.new
$ test -s input.ppm.new
$ head -c 2 input.ppm.new
P6
$ mv input.ppm.new input.ppm

The mv command changes the directory entry, so it is the one state-changing step in this sequence. If conversion or verification fails, leave input.ppm alone and investigate the error. Remove the incomplete input.ppm.new only once you have confirmed it is the failed temporary file. For a more complicated workflow, make a separate backup first.

4. Replace Several Colours in One Pass

Supply more old/new pairs in sequence. The command accepts up to 256 pairs:

$ ppmchange red blue green yellow input.ppm > two-colour-replacements.ppm

Here red becomes blue and green becomes yellow. If a pixel matches more than one old colour, the leftmost pair wins, an ordering that is easy to miss when similar colours are involved. Put the most specific intended match first and keep the command readable.

Do not confuse a pair with the input filename. Every colour replacement needs two arguments. If the final colour argument is missing, the program cannot interpret the command as intended, so re-run with the exact pair list and check the generated file rather than trying to repair a partial binary stream.

5. Replace Near Matches With Closeness

Use -closeness=10 when a small variation around the requested colour should also match:

$ ppmchange -closeness=10 red blue input.ppm > nearby-reds-to-blue.ppm

The default closeness is 0, exact matching. The percentage is based on Netpbm's normalised Cartesian sum of the red, green and blue differences: not a perceptual distance, and it has no idea that two differently lit areas might belong to the same object. A larger value can replace pixels that merely happen to sit numerically close.

Warning

Use a small value first, inspect the result, and keep the original image. This option can change more pixels than expected, especially in photographs or images with gradients. There is no undo inside ppmchange; recovery means rerunning from the untouched original with a narrower match, or restoring your saved output.

6. Set a Remainder Colour for a Mask-Like Result

Without -remainder, colours you did not name pass through unchanged. With it, every pixel that did not get an explicit replacement is set to one colour:

$ ppmchange -remainder=black red white input.ppm > red-mask.ppm

This turns exact red pixels white and everything else black. Useful for a simple mask, but deliberately destructive to the other colours in the output. The input stays untouched because the output is redirected to a new file.

You can combine a remainder with several explicit pairs; it only applies after the explicit matches have been considered. Verify both the header and the visual result before using the mask in a later pipeline.

7. Handle maxval Warnings

PPM stores a maximum sample value called maxval. The output keeps the input image's maxval. If a requested new colour cannot be represented exactly at that scale, ppmchange uses the nearest representable colour and, unless -closeok is supplied, warns about the approximation.

This matters particularly when a source came from PBM, whose maxval is normally 1. A black-and-white source cannot represent ordinary RGB shades accurately just because you supply colour names. Inspect the input first, and use pamdepth to build a suitable maxval before colourising when that is appropriate:

$ pamdepth 255 input.ppm > input-255.ppm
$ ppmchange red blue input-255.ppm > recoloured.ppm

Only use -closeok when the approximation is understood and acceptable:

$ ppmchange -closeok red blue input.ppm > recoloured.ppm

This option suppresses the warning; it does not increase the image's precision. Do not use it to hide unexpected output in an automated job. Capture diagnostics and verify the resulting image when the exact colour matters.

8. Diagnose Failures Without Guessing

An input error usually means the path is wrong, the file is empty, or it is not a valid Netpbm image. Check those facts without changing the image:

$ ls -l /path/to/input.ppm
$ test -r /path/to/input.ppm && echo readable
$ head -c 2 /path/to/input.ppm
P3

A source can use P3 for plain-text PPM or P6 for raw binary PPM. The output may be binary even when the input is plain text. If the header is missing or the command reports an invalid magic number, stop and locate the correct source rather than piling on more options.

If the result looks unchanged, check whether the pixels are exact matches, whether the requested pair is ordered correctly, and whether the source maxval can represent the requested colour. Add a small closeness value only once you have weighed the risk of replacing neighbouring shades. None of these checks need elevated privileges.

Done means

  • The installed ppmchange and Netpbm version were checked.
  • The source PPM remains available and the output was written to a separate path first.
  • Exact replacements, pair ordering and any remainder behaviour are understood.
  • Closeness was used deliberately, with the original retained for recovery.
  • The output header and exit status were checked, and maxval warnings were not hidden by accident.