Convert a FaceSaver File to PGM with fstopgm
fstopgm turns a Usenix FaceSaver file into a PGM greyscale image, and a quick check afterwards confirms you got the dimensions you expect. The examples use Netpbm 11.5.2, installed here as 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 readable FaceSaver file, a shell, and the Netpbm package. This is a file conversion, so it normally needs no elevated privileges. Do not use sudo unless the input or destination directory is deliberately restricted, and you have already checked the ownership and permissions.
1. Check the installed command
Confirm the executable and version before building a script around it. These are ordinary, read-only checks:
$ command -v fstopgm
/usr/bin/fstopgm
$ fstopgm --version
fstopgm: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
fstopgm: Built from source dated 2024-03-31 09:09:47
The version text includes build details and may contain extra lines. The useful checkpoint is that the command resolves to the expected binary and reports Netpbm 11.5.2, or the version you have installed. The package version and command version are related, but they are not the same string.
2. Convert the FaceSaver file
Choose a new output name, and pass the input path as the only positional argument:
$ fstopgm /path/to/face.fs > face.pgm
fstopgm writes the PGM image to standard output. A successful command may therefore print nothing to the terminal, because the shell sends that output to face.pgm. It does not edit the FaceSaver file.
Checkpoint
Verify that the destination exists, and is recognised as a greyscale Netpbm image:
$ file face.pgm
face.pgm: Netpbm image data, size 640 x 480, rawbits, greymap
Your dimensions will differ. The meaningful checks are that the file is non-empty, the reported format is a greymap or PGM image, and the dimensions are plausible for the source.
3. Protect an existing output file
Shell redirection with > truncates an existing destination before fstopgm starts. That makes a typo or a malformed input capable of destroying a useful PGM. Use a fresh temporary name, then replace the destination only after checking it:
$ fstopgm /path/to/face.fs > face.pgm.new
$ file face.pgm.new
face.pgm.new: Netpbm image data, size 640 x 480, rawbits, greymap
$ mv face.pgm.new face.pgm
- Do not run
mvearly. Wait until the new file has passed your checks. - Clean up carefully. If conversion fails, leave the old file alone and remove only the incomplete
face.pgm.newafter inspecting it. Removing a file is irreversible unless you have a backup.
4. Use standard input when the file is in a pipeline
The input argument is optional. Omitting it makes fstopgm read the FaceSaver data from standard input, which is useful when another command supplies the file:
$ cat /path/to/face.fs | fstopgm > face-from-stdin.pgm
$ file face-from-stdin.pgm
face-from-stdin.pgm: Netpbm image data, size 640 x 480, rawbits, greymap
For a plain file, the direct form in step 2 is easier to read. Avoid feeding text-processing commands into this pipeline: the FaceSaver header is text, but its image data is not necessarily suitable for tools that expect a text stream.
5. Check for rectangular pixels
Some FaceSaver files describe pixels that are rectangular rather than square. fstopgm preserves the image data and does not rescale those pixels. First run a probe with output discarded:
$ fstopgm /path/to/face.fs > /dev/null
Read any guidance printed by the command. If the file needs correction, the message gives the precise pamscale command arguments to use. Apply that scaling between fstopgm and the later processing command, for example:
$ fstopgm /path/to/face.fs | pamscale REPLACE_WITH_THE_ARGS_REPORTED_BY_FSTOPGM | pnmnorm > face-normalised.pgm
Replace the uppercase placeholder with the arguments from your own probe. Do not guess them from the image dimensions. If the probe prints nothing about scaling, the straightforward conversion is the appropriate next step.
6. Normalise or make a bitmap
The PGM output can be passed to other Netpbm tools. To normalise its grey range:
$ fstopgm /path/to/face.fs | pnmnorm > face-normalised.pgm
To produce a black-and-white image, the fstopgm manual recommends enlarging first so that fine detail is less likely to disappear, then normalising and dithering:
$ fstopgm /path/to/face.fs | pamenlarge 3 | pnmnorm | pamditherbw > face.pam
On this Netpbm 11.5.2 installation, file face.pam reports a Netpbm PAM image. The exact container and diagnostic wording can vary with the installed Netpbm build, so check the result rather than relying on the filename:
$ file face.pam
face.pam: Netpbm PAM image file, size = 1920 x 1440
These programs are separate pipeline stages. Check that each one is installed with command -v pnmnorm pamenlarge pamditherbw pamscale before using the relevant pipeline. An unavailable later tool does not mean the FaceSaver conversion failed; save and inspect the PGM first.
7. Diagnose a failed conversion
A missing or unreadable input usually means the path or permissions are wrong:
$ ls -l /path/to/face.fs
$ test -r /path/to/face.fs && echo readable
If the input is not a valid FaceSaver file, the installed command reports an error such as fstopgm: error reading header and exits non-zero. Keep the diagnostic on the terminal while redirecting only standard output to a file:
$ fstopgm /path/to/suspect.fs > suspect.pgm
$ printf 'exit status: %s\n' "$?"
exit status: 1
Warning
Do not treat the existence of suspect.pgm as proof of success. A failed command can leave a truncated file because redirection happens first. Use the temporary-output pattern from step 3 when the destination matters, and keep the original FaceSaver file until the resulting image has been viewed or checked by another Netpbm tool.
Done means
- Version confirmed.
fstopgmis installed, and its Netpbm version is known. - Source untouched. The FaceSaver file was converted to a non-empty PGM without altering the source.
- Dimensions checked.
filereports sensible greyscale image dimensions. - Scaling came from the probe. Any rectangular-pixel instruction came from the command's own probe, not a guess.
- Output protected. An existing output was protected from accidental truncation.
- Extra steps verified. Any extra normalisation or bitmap conversion was checked as a separate pipeline stage.