Invert PNM Images Safely with pnminvert
You will produce a new PNM image with its brightness inverted, while leaving the source file untouched. The examples cover grayscale and RGB images, binary and plain output, standard input, and checks that catch a bad path or an unexpected result.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need the netpbm package and a readable PGM, PPM or other PNM file. The installed command used for these examples is Netpbm 11.5.2 from package version 2:11.05.02-1.1build1. Its manual page is old, so the version check is worth keeping in operational notes.
Checkpoint
You are about to write a separate output file. Do not redirect to the only copy of an image unless you have a verified backup. Shell redirection can truncate the destination before pnminvert gets to read it.
1. Confirm the installed command
Check the executable and package version as your normal user. Neither command changes files:
$ command -v pnminvert
/usr/bin/pnminvert
$ pnminvert --version
pnminvert: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pnminvert: 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 output includes build details and then exits successfully. The command has no pnminvert-specific option for selecting an input or output format. Its normal interface is one optional input filename, with the transformed PNM image written to standard output.
2. Invert a grayscale image into a new file
Pass the source as the optional filename and redirect standard output to a new destination. Replace the example paths with files you own:
$ pnminvert input.pgm > inverted.pgm
$ printf 'status: %s\n' "$?"
status: 0
For a grayscale pixel, the command calculates the complementary value, maxval - G. With a maximum value of 255, black becomes white, white becomes black, and a middle value changes to its complement. The input file is not modified by this command.
Verify both the image type and its dimensions before opening it in another program:
$ pnmfile input.pgm inverted.pgm
input.pgm: PGM raw, 640 by 480 maxval 255
inverted.pgm: PGM raw, 640 by 480 maxval 255
The dimensions and maximum value should normally match. The exact description depends on the input and the installed Netpbm tools. If pnmfile reports an error, stop and inspect the source rather than replacing it.
3. Use plain text output when a text PNM is useful
Netpbm commonly writes a raw, binary PNM by default. That is efficient, but it is awkward to inspect in a terminal. The shared libnetpbm -plain option requests the plain-text variant:
$ pnminvert -plain input.pgm > inverted-plain.pgm
$ sed -n '1,8p' inverted-plain.pgm
P2
640 480
255
255 254 253 252
The sample pixel values are illustrative: your image will produce different numbers. The significant checks are the P2 header for plain grayscale output and a successful exit status. Use -plain only when readability or compatibility requires it, because plain files are usually larger.
4. Invert an RGB image
Colour images are handled component by component. Red, green and blue each receive the same complementary calculation; the command does not convert the image to grayscale first:
$ pnminvert photograph.ppm > photograph-inverted.ppm
$ pnmfile photograph.ppm photograph-inverted.ppm
photograph.ppm: PPM raw, 1920 by 1080 maxval 255
photograph-inverted.ppm: PPM raw, 1920 by 1080 maxval 255
For an RGB component with maximum value 255, a value of 20 becomes 235. Applying the operation separately to all three components preserves the image dimensions and PPM structure while reversing the colour relationships.
Checkpoint
Compare the metadata before deleting anything. If the output has the wrong dimensions or a different file type than expected, keep the original and investigate the input format.
5. Use a pipeline without creating an intermediate input name
With no filename, pnminvert reads standard input. This makes it fit ordinary shell pipelines:
$ pnminvert < input.pgm > inverted-from-stdin.pgm
$ pnmfile inverted-from-stdin.pgm
inverted-from-stdin.pgm: PGM raw, 640 by 480 maxval 255
Keep the input and output paths distinct when using redirection. If another command supplies the PNM data, check that it really emits PNM rather than a PNG, JPEG or diagnostic message. A successful shell pipeline is not proof that the content is the image you intended, so inspect the output file as well.
6. Handle failures and recover safely
A missing or unreadable input is an error. Capture the status when a script needs to stop on failure:
$ if pnminvert missing.pgm > inverted.pgm; then
> printf '%s\n' 'inversion complete'
> else
> status=$?
> printf 'pnminvert failed with status %s\n' "$status" >&2
> fi
pnminvert: Unable to open file 'missing.pgm' for reading. fopen() returns errno 2 (No such file or directory)
pnminvert failed with status 1
The diagnostic and exact wording can vary. The non-zero status is the part a script should trust. Because the shell creates inverted.pgm before starting the command, a failed run may leave an empty or partial destination. Treat it as disposable: choose a new destination, or remove only that known output after checking its path. The source remains available unless you explicitly overwrote it earlier.
Do not use sudo for ordinary image conversion. If the input directory is protected, copy the source to a location you can read, or fix its ownership and permissions through your normal change process. Elevated privileges do not make a malformed PNM valid.
Done means
- The installed Netpbm version and executable path are known.
- The original image is still present and the inverted image is a separate file.
pnmfileconfirms the expected PNM type, dimensions and maximum value.- Grayscale output uses complementary brightness, and RGB output inverts each component separately.
- Scripts check the command's non-zero status and do not treat a failed redirected output as usable.
- No elevated privilege or persistent configuration change was needed.