Convert a PGM Image to FaceSaver with pgmtofs
pgmtofs reads a PGM greyscale image and writes it out in the old Usenix FaceSaver format, ready for the handful of tools that still expect it. Allow about ten minutes for a repeatable conversion into a separate output file.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use Netpbm 11.5.2, packaged here as netpbm 2:11.05.02-1.1build1.
- You need: a shell, the Netpbm package, a PGM image, and enough disk space for a second copy of the converted data.
- It will not touch: the source image, and it installs nothing. The output is an image file rather than terminal text, so do not print it straight to your screen.
1. Check the installed command
Confirm that the executable and package are the ones you expect. These are ordinary, read-only commands that need no elevated privileges:
$ command -v pgmtofs
/usr/bin/pgmtofs
$ pgmtofs --version
pgmtofs: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
The version output includes build details as well as the Netpbm version. Exact package versions and build dates will vary on another host.
Checkpoint
Continue only if command -v finds the intended binary and the version is recorded for your conversion notes.
2. Check that the input is really PGM
pgmtofs accepts one optional input filename, and reads standard input when none is given. The PGM specification supports raw files beginning with P5 and plain files beginning with P2; both describe a greyscale raster with a width, height, maximum value and pixel data.
Inspect the file before converting it:
$ file INPUT.pgm
$ head -n 5 INPUT.pgm
A plain PGM has a readable header. A raw PGM contains binary raster data, so head may show unreadable characters after the header. Use a format-aware Netpbm tool for a stronger check:
$ pamfile INPUT.pgm
INPUT.pgm: PGM raw, 640 by 480 maxval 255
The dimensions and maximum value above are examples, not defaults: check that they match the image you actually intend to convert. In PGM, zero is black and the maximum value is white.
3. Convert to a new FaceSaver file
Choose an output path that does not already hold data, then run the conversion:
$ pgmtofs INPUT.pgm > OUTPUT.face
The filename suffix is only a convention: pgmtofs writes FaceSaver data to standard output, and it is the shell redirection that actually creates OUTPUT.face. The program has no options specific to it. It does recognise the options common to Netpbm programs, but add one only after checking the installed common-options documentation.
Safety warning
Shell redirection can truncate an existing destination before the program runs. Use a new filename, or check first:
$ if test -e OUTPUT.face; then
> printf '%s\n' 'Refusing to overwrite OUTPUT.face' >&2
> exit 1
> fi
$ pgmtofs INPUT.pgm > OUTPUT.face
$ printf 'exit status: %s\n' "$?"
exit status: 0
Recovery
If you accidentally replace a file, stop using that path and recover it from your normal backup or snapshot. There is no undo operation in pgmtofs.
4. Verify the result without treating it as text
Check that the command created a non-empty output, and that it is not merely a copied PGM header:
$ wc -c OUTPUT.face
$ xxd -g1 -l 96 OUTPUT.face
On the installed build, a small test conversion begins with FaceSaver metadata such as FirstName:, LastName: and E-mail:. The exact byte count depends on the input dimensions and the generated metadata, so do not compare the complete output byte-for-byte with another host unless the inputs and tool builds are identical.
A successful exit status only confirms that the program completed its read and write. It does not prove that a receiving application accepts every image dimension or display convention. If the destination system has its own importer, use that as the final compatibility check.
5. Use standard input in a pipeline
Because the input filename is optional, another program can supply the PGM stream:
$ generate-pgm-image | pgmtofs > OUTPUT.face
Keep the output redirection separate from the input pipeline, so it stays clear which command produces PGM data and which produces FaceSaver data. For a saved PGM, the equivalent form is:
$ cat INPUT.pgm | pgmtofs > OUTPUT.face
The pipeline form is handy for testing, but it will not make a bad upstream image valid. Check the producer's exit status if the pipeline is part of a script, and enable pipeline failure reporting where your shell supports it:
$ set -o pipefail
$ image-producer | pgmtofs > OUTPUT.face
$ printf 'pipeline status: %s\n' "$?"
If your shell does not support pipefail, capture and check the producer's status using that shell's own pipeline facilities.
6. Recover from the common failures
- Missing input file. That normally produces a non-zero status and an error on standard error. Check spelling, path and permissions before adding
sudo; elevated privileges are not normally needed to read an image in a directory you can already access. - Not a valid PGM. Convert or regenerate it with a tool that can write PGM, then inspect it again with
pamfile. Do not just rename a PNG or JPEG to.pgm; the suffix does not change the contents. - Write fails. Check the destination directory, free space and ownership. Avoid running the whole conversion as root merely to paper over a permissions problem. Writing to a shared or removable location works better as: write to a local temporary path first, verify it, then copy it across with the permissions that destination requires.
To inspect a FaceSaver file later, the related fstopgm command converts it back to PGM. That is a separate conversion, not an undo operation that restores the original file byte-for-byte:
$ fstopgm OUTPUT.face > ROUNDTRIP.pgm
$ pamfile ROUNDTRIP.pgm
Done means
- Confirmed the versions. You checked the installed pgmtofs and Netpbm versions.
- Verified the source. You confirmed it is a real PGM and recorded its dimensions.
- Wrote to a safe destination. FaceSaver output went to a new file rather than risking the source.
- Checked the result. You confirmed the exit status, byte count and initial bytes.
- Know the option boundary. pgmtofs has no tool-specific options and reads standard input when no filename is supplied.
- Have a backup ready. A backup or snapshot exists before you replace any existing file.