Repair Truncated and Invalid Netpbm Images with pamfix
You will finish with a valid Netpbm image salvaged from a file that is shorter than its header claims, or from one containing sample values above its stated maximum. The examples use pamfix from Netpbm 11.5.2, installed here as package version 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 fifteen minutes. You need a shell, a readable Netpbm image, and enough free space for a separate output file. The normal commands are unprivileged. Do not use sudo merely because an image is damaged.
Safety boundary
Pamfix writes a repaired image to standard output. It does not edit the input file unless you deliberately redirect output over it. Keep the original until the repaired image has passed your checks.
1. Check the installed command
Confirm which binary is being used and record the Netpbm version. This is a read-only checkpoint:
$ command -v pamfix
/usr/bin/pamfix
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ pamfix --version 2>&1 | head -3
pamfix: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pamfix: Built from source dated 2024-03-31 09:09:47
pamfix: Built by Debian
The command accepts an input file name, or reads standard input when you omit it. Its output is always a Netpbm image on standard output. The manual also permits unique option abbreviations and double hyphens, but full option names are easier to review in scripts.
2. Test whether the file is actually truncated
A truncated stream is missing data at the end. pamfix assumes the missing part is at the bottom of the image and emits only the complete rows it can read. Before repairing, use pamfile --allimages to check for a file that is too small:
$ pamfile --allimages /path/to/damaged.pam
pamfile: Error reading ...
The exact diagnostic depends on the input format and the point at which reading stops. A successful check does not prove that the picture is visually correct, and a failed check does not prove that pamfix can recover useful pixels. It only identifies a size problem worth investigating.
Checkpoint
Make a working copy before writing any output. This copy operation is ordinary and does not need elevated privileges:
$ cp --preserve=all /path/to/damaged.pam /path/to/damaged.pam.original
$ ls -l /path/to/damaged.pam /path/to/damaged.pam.original
3. Salvage complete rows from a short stream
Use -truncate for an image whose final rows are missing. Redirect to a new name, not back to the input:
$ pamfix -truncate /path/to/damaged.pam > /path/to/repaired-truncated.pam
pamfix: Copying 480 good rows; 16 bottom rows missing. Use -verbose to find out why
$ pamfile --allimages /path/to/repaired-truncated.pam
/path/to/repaired-truncated.pam: Image 0: PPM raw, 1920 by 480 maxval 255
The row counts and dimensions above are examples of the shape of the diagnostic, not values to copy blindly. Your output should have the same width and format as the readable part, but fewer rows. pamfix also omits a partial final row rather than emitting incomplete raster data.
Use -verbose when you need to understand where reading stopped:
$ pamfix -truncate -verbose /path/to/damaged.pam > /path/to/repaired-truncated.pam
pamfix: Error reading row 480: End of file encountered when trying to read a row from input file.
pamfix: Copying 480 good rows; 16 bottom rows missing
If the source was short because the generating program had a bug, the surviving rows may still make a garbage picture. Open or convert the result before replacing anything. pamfix cannot reconstruct information that was never written.
4. Choose a policy for excessive sample values
Netpbm headers contain a maxval. A pixel sample above that value is invalid, and ordinary Netpbm readers may reject the image. pamfix offers three different policies:
| Option | Effect | Use it when |
|---|---|---|
-clip | Replace each excessive value with the header's maxval. | You want to retain the image size and keep the existing scale. |
-changemaxval | Raise maxval to accommodate the largest value. | You want to retain the sample values and accept a changed scale. |
-truncate | Stop at the first invalid sample and retain only earlier valid data. | You prefer earlier valid data over guessing how to reinterpret later samples. |
Do not combine -clip and -changemaxval. The installed command rejects that combination. These policies are not interchangeable: clipping changes bright pixels, while raising maxval changes the meaning of every sample as a fraction of the new maximum.
5. Repair excessive values into a new file
Choose one policy and verify the resulting header. For clipping:
$ pamfix -clip /path/to/invalid.pgm > /path/to/repaired-clipped.pgm
$ pamfile --allimages /path/to/repaired-clipped.pgm
/path/to/repaired-clipped.pgm: Image 0: PGM raw, 1920 by 1080 maxval 255
With -verbose, pamfix reports the row, column and plane of each value it clips. The coordinates are useful evidence when you need to find the source of the corruption:
$ pamfix -clip -verbose /path/to/invalid.pgm > /path/to/repaired-clipped.pgm
pamfix: Clipping: Row 0 Col 1 Plane 0. Sample value 300 exceeds the image maxval of 255
For a workflow that preserves the value instead, use:
$ pamfix -changemaxval /path/to/invalid.pgm > /path/to/repaired-raised-maxval.pgm
$ pamfile --allimages /path/to/repaired-raised-maxval.pgm
/path/to/repaired-raised-maxval.pgm: Image 0: PGM raw, 1920 by 1080 maxval 300
Do not compare the two files only by whether they open. Check the maxval and inspect the image. A raised maxval can make the same stored values represent darker pixels relative to the new scale; clipping can flatten highlights.
6. Check failures without escalating privileges
If pamfix reports a bad magic number, the input is not a PAM, PPM, PGM or PBM stream that this command recognises. Check the path and type rather than retrying with sudo:
$ test -r /path/to/damaged.pam && echo readable
readable
$ file /path/to/damaged.pam
/path/to/damaged.pam: Netpbm image data
A non-zero exit status means the repair did not complete successfully. Treat any redirected output from a failed run as disposable. Write to a temporary or clearly named destination, then replace the original only after checking the result.
If you did create an unwanted incomplete destination, remove that destination explicitly after confirming its path. To undo a deliberate replacement, restore the preserved copy:
$ cp --preserve=all /path/to/damaged.pam.original /path/to/damaged.pam
$ pamfile --allimages /path/to/damaged.pam
That restore overwrites the current path, so check both names before pressing Enter. No service restart or persistent configuration change is part of pamfix's normal workflow.
Done means
- You confirmed the installed pamfix and Netpbm 11.5.2 versions.
- The original image remains available as a separate file.
- You chose
-truncate,-clipor-changemaxvalfor a stated reason. - The repaired output passes
pamfile --allimagesand has the expected dimensions and maxval. - You inspected the repaired image before replacing any useful file.
- You did not combine
-clipwith-changemaxvalor use elevated privileges without a separate permission reason.