Convert PAM Images to PNM Safely with pamtopnm
You will finish with a repeatable way to turn a PAM image into PBM, PGM or PPM, while knowing which output format the installed program will choose. The examples use Netpbm 11.5.2, provided here by Debian package netpbm 2:11.05.02-1.1build1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell, an input PAM or PNM file, and enough free space for the output. The commands are ordinary user commands. They read the input and write standard output, so they do not change the source file or require elevated privileges.
1. Confirm the installed command
Check the binary and package before relying on behaviour from a different Netpbm release:
$ command -v pamtopnm
/usr/bin/pamtopnm
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ pamtopnm --version
pamtopnm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
The version diagnostic also prints build details on this installation. Exact diagnostic lines vary by package build, so use the package query as the stable checkpoint.
2. Convert a PAM file to a named output
Give the input path as the final argument and redirect standard output to a new file:
$ pamtopnm /path/to/input.pam > /path/to/output.pnm
$ file /path/to/output.pnm
/path/to/output.pnm: Netpbm image data, ...
Replace both paths with real values. The command does not infer the output filename or append an extension. The file output is a quick check, but the PNM header is the better format test:
$ head -n 3 /path/to/output.pnm
P6
2 1
255
The dimensions and maxval in that output are illustrative. For a real PPM file, the header starts with P6; a PGM file starts with P5; and a PBM file starts with P4. Binary pixel data follows the header, so do not open the output in a text editor or use a command that reads the whole file as text.
Checkpoint: if the redirection succeeds, the shell creates or truncates the destination before pamtopnm runs. Use a new destination while testing. If conversion fails, remove the incomplete output with rm -- /path/to/output.pnm, then choose a different destination or restore it from your normal backup. Do not use sudo to work around a path or ownership mistake.
3. Predict the output from depth and maxval
pamtopnm chooses the PNM family from the PAM header's depth, not from the visible colours in the pixels:
- Depth 3 or 4 produces PPM.
- Depth 1 or 2 produces PBM when
MAXVALis 1, otherwise PGM.
That means an RGB image whose pixels happen to be grey still produces PPM. Conversely, a grayscale image whose pixels are only black and white does not automatically become PBM when its maxval is higher than 1.
Here is a safe in-memory fixture. It creates a two-pixel RGB PAM stream, converts it, and prints only the first header bytes:
$ printf 'P7\nWIDTH 2\nHEIGHT 1\nDEPTH 3\nMAXVAL 255\nTUPLTYPE RGB\nENDHDR\n\000\200\377\377\000\000' \
| pamtopnm | od -An -tc -N 15
P 6 \n 2 1 \n 2 5 5 \n
The leading P6 confirms that the RGB input became binary PPM. The bytes after the header are pixel data, so their appearance in an od listing is not a meaningful text check.
4. Handle tuple type failures
Without options, the PAM tuple type and depth must describe data suitable for PBM, PGM or PPM. A depth-1 image labelled RGB, for example, is rejected because RGB needs at least three channels:
$ pamtopnm /path/to/alpha.pam > /tmp/alpha.pnm
pamtopnm: Depth 1 is insufficient for tuple type 'RGB'. Minimum depth is 3
$ printf 'exit status: %s\n' "$?"
exit status: 1
The path and header in this example must refer to a matching fixture, such as a PAM header with DEPTH 1 and TUPLTYPE RGB. The diagnostic shown is from the installed Netpbm build. A non-zero status means the output is not a trustworthy conversion. Check the PAM header first. Confirm that DEPTH, MAXVAL and TUPLTYPE agree with the data rather than changing the label to silence the error.
If you have independently verified that the tuple values already contain the channels expected by PNM, -assume bypasses the tuple type requirement:
$ pamtopnm -assume /path/to/verified-input.pam > /path/to/verified-output.pnm
$ printf 'exit status: %s\n' "$?"
exit status: 0
This option is an assertion, not a repair. It does not change the depth, rearrange channels or discard alpha. The depth must still conform. If it does not, use a suitable Netpbm transformation such as pamchannel first, then inspect the resulting header.
Warning: do not use -assume on an untrusted or merely unfamiliar file. You are taking responsibility for the channel interpretation, and a successful command can still produce misleading image data.
5. Use pamtopnm in a pipeline
With no input filename, the program reads standard input. This is useful when a preceding program emits PAM, or when a pipeline must accept either PAM or PNM:
$ generate-pam | pamtopnm | image-consumer
Netpbm programs that read PAM also read PNM as if it were PAM. If the input is already PBM, PGM or PPM, pamtopnm therefore reduces to copying it to standard output. Keep the pipeline's exit status visible while debugging, and redirect final output explicitly if the consumer is a file-writing command.
Done means
pamtopnm --versionidentified the local Netpbm build.- The output was redirected to an intentional destination and its first magic value was checked.
- You predicted PBM, PGM or PPM from depth and maxval, not from how the image looks.
- You treated
-assumeas a verified data assertion, not as a general conversion switch.