Smooth a Netpbm Image Safely with pnmsmooth
pnmsmooth blurs out noise by replacing each pixel with the average of its neighbours, using a rectangular convolution matrix. Allow about ten minutes for a single image, including verification.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use Netpbm 11.5.2, package version 2:11.05.02-1.1build1 on this machine. You need a readable PNM input such as a PPM file, a shell, and somewhere to write the output. Image conversion is normally unprivileged; do not use sudo unless the input or destination permissions genuinely require it.
1. Check the installed command
Confirm which binary will run and record its Netpbm version. These are read-only checks:
$ command -v pnmsmooth
/usr/bin/pnmsmooth
$ pnmsmooth --version 2>&1 | sed -n '1,2p'
pnmsmooth: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pnmsmooth: Built from source dated 2024-03-31 09:09:47
The command takes a PNM file argument and writes the smoothed image to standard output. Leave the argument off and it reads from standard input instead, useful in a pipeline but an easy way to lose track of source and destination.
Checkpoint
Make sure command -v points at the Netpbm installation you actually intend to use. Package versions and build dates will differ elsewhere.
2. Preserve the source before writing output
Pick a new output name. Shell redirection with > truncates an existing destination the moment pnmsmooth starts, so never point it at the original image or the only copy of a result you care about.
$ INPUT='/path/to/source.ppm'
$ OUTPUT='/path/to/source-smoothed.ppm'
$ test -r "$INPUT" && echo 'input is readable'
input is readable
$ test ! -e "$OUTPUT" && echo 'output name is unused'
output name is unused
If the destination already exists and you need to keep it, choose another name or make an explicit backup first:
$ cp --preserve=all "$OUTPUT" "$OUTPUT.bak"
$ pnmsmooth "$INPUT" > "$OUTPUT.new"
$ mv "$OUTPUT.new" "$OUTPUT"
The mv only replaces the old destination once the new file exists. If smoothing fails, leave the original destination alone and inspect the diagnostic. Removing the backup is the irreversible step, so do that separately once you have checked the image.
3. Smooth with the default 3 by 3 window
Run pnmsmooth with no size options and it uses a default convolution matrix of three columns by three rows:
$ pnmsmooth "$INPUT" > "$OUTPUT"
pnmsmooth: Running Pnmconvol -normalize -matrix=1,1,1;1,1,1;1,1,1
That diagnostic goes to standard error while the image goes to standard output; it identifies the normalised matrix, not a progress percentage. A successful run should leave a non-empty PNM file:
$ test -s "$OUTPUT" && echo 'output is non-empty'
output is non-empty
$ pamfile "$OUTPUT"
/path/to/source-smoothed.ppm: PPM raw, 1600 by 1200 maxval 255
Your own dimensions, and whether the PPM comes out plain or raw, will vary. The useful checks are that pamfile recognises it as a PNM image with the dimensions you expect.
4. Choose a larger or non-square window
Use -width and -height when a 3 by 3 average is not enough smoothing:
$ pnmsmooth -width=5 -height=3 "$INPUT" > "$OUTPUT"
pnmsmooth: Running Pnmconvol -normalize -matrix=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1
- These describe the convolution window, not a resize. Five by three here does not mean five output columns by three output rows.
- A larger window averages more neighbours and generally produces a softer result.
- Keep the dimensions explicit in scripts so a reader is not left guessing the defaults.
The image must be large enough for the kernel you pick: a five-column kernel cannot convolve an image that is only five columns wide, and the same limit applies to rows. If the command complains the image is too narrow or too short, use a smaller window or a bigger source. Check the source first:
$ pamfile "$INPUT"
/path/to/source.ppm: PPM raw, 1600 by 1200 maxval 255
Common traps
Older instructions may show pnmsmooth -size 5 5 image.ppm. The installed command keeps -size for backward compatibility, taking width and height as the next two arguments, but new scripts should use -width and -height instead: the modern form makes the values visible and lets you build a rectangular window without guesswork.
Do not build a workflow around -dump: on this installation it is rejected outright with a message saying the option no longer exists. Older Netpbm documentation described several different dump behaviours before that option disappeared. If you need to construct a convolution explicitly, use the current pnmconvol interface rather than copying an old dump example.
5. Check the result and recover from a failure
Inspect the output with pamfile or your usual image viewer. For a second, format-level check, convert a copy to PNG if pnmtopng is installed:
$ pnmtopng "$OUTPUT" > /tmp/source-smoothed.png
$ file /tmp/source-smoothed.png
/tmp/source-smoothed.png: PNG image data, 1600 x 1200, 8-bit/color RGB, non-interlaced
That PNG is a separate conversion, not something pnmsmooth itself produced. If the output is empty, or pamfile cannot read it, keep the source, remove only the failed new file, and rerun to a fresh destination after reading the diagnostic:
$ rm -- "$OUTPUT.new"
$ pnmsmooth -width=3 -height=3 "$INPUT" > "$OUTPUT.new"
$ pamfile "$OUTPUT.new"
$ mv "$OUTPUT.new" "$OUTPUT"
Warning
Never remove the source as a cleanup step. Smoothing is lossy: the original pixels cannot be reconstructed from the averaged output.
Done means
- Version checked: the installed binary and Netpbm version are known.
- Source protected: the input is untouched and the destination was not accidentally truncated.
- Window explicit: when it is not the default 3 by 3 matrix.
- Output verified:
pamfilerecognises it with the expected dimensions. - Failures recoverable: a bad temporary output can be discarded without losing the source or a previous good result.