Sharpen Netpbm Images Safely with pammasksharpen
pammasksharpen applies classic unsharp masking to a Netpbm image: blur a copy, compare it to the original, and push the difference back in. This guide builds that mask and runs the sharpen step on Netpbm 11.5.2, 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 15 minutes for a first run. You need the Netpbm package, a readable input image, and enough free space for the intermediate files. None of this needs sudo, and nothing here alters a service or system configuration.
1. Check the installed command
Confirm the executable is available and record the version that will process your image:
$ command -v pammasksharpen
/usr/bin/pammasksharpen
$ pammasksharpen --version
pammasksharpen: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pammasksharpen: Built from source dated 2024-03-31 09:09:47
The installed manual page is dated June 2006, but its rules still describe the local command: the mask comes first, the original input comes second, and the sharpened image goes to standard output. Keep that argument order visible in scripts, because swapping the two files produces a plausible-looking but wrong result.
2. Build a Gaussian mask
An unsharp mask is usually a blurred version of the original. The Netpbm manual's reproducible pipeline starts with pamgauss, which emits a Gaussian kernel, then converts that kernel to PGM for pnmconvol:
$ pamgauss 5 5 -sigma=.7 -tupletype=GRAYSCALE | pamtopnm > gauss.pgm
$ pnmfile gauss.pgm
gauss.pgm: PGM raw, 5 by 5 maxval 255
The kernel is 5 by 5, so it represents a radius of 2 pixels: the radius is half the kernel width after subtracting its centre, or (5 - 1) / 2. A larger odd square kernel affects detail over a wider area. Start small, especially for faces or fine texture: a large radius can erase detail rather than improve it.
Do not confuse the Gaussian kernel with the final mask. It is only the recipe for blurring. The next step applies it to the actual image.
3. Blur the source image
Run pnmconvol with the kernel file and your source image. The -nooffset option is required for the kernel made by pamgauss:
$ pnmconvol -nooffset gauss.pgm /path/to/input.ppm > blurred.ppm
$ pnmfile /path/to/input.ppm blurred.ppm
/path/to/input.ppm: PPM raw, 1600 by 1200 maxval 255
blurred.ppm: PPM raw, 1600 by 1200 maxval 255
The output format stays a Netpbm format, but the exact file spelling depends on your input and installed tools. Check the dimensions and maxval, not just the filename. The convolution tool copies edge pixels directly when the kernel would extend beyond the image; an image smaller than the kernel can fail outright instead of producing a useful mask.
Checkpoint
Stop here and inspect blurred.ppm if the result looks unexpectedly dark, clipped or unchanged. Do not continue until the blur is a valid image with the same dimensions as the source.
4. Sharpen without replacing the source
Pass the blurred image first and the original image second. Redirect standard output to a fresh destination:
$ pammasksharpen -sharpness=1.2 -threshold=.02 blurred.ppm /path/to/input.ppm > sharpened.ppm
$ pnmfile sharpened.ppm
sharpened.ppm: PPM raw, 1600 by 1200 maxval 255
- -sharpness is the amount applied to the difference between the original sample and the matching mask sample. Default is
1.0, must be a non-negative real number, and zero disables sharpening. The1.2above is a starting point, not a universal best value. - -threshold ignores small differences, which can cut speckling in smooth areas. It is a fraction of the image maxval, between
0and1.0, and defaults to0, so every difference counts unless you set one. Raise it cautiously: too much removes genuine low-contrast detail.
The mask and input must have identical dimensions and the same maxval. If the command rejects them, check both files with pnmfile and rebuild the mask from the same source. The program clips samples that would fall outside the representable range, so a strong setting can flatten bright or dark areas.
5. Protect an existing output
Shell redirection with > truncates its destination before the command runs. If sharpened.ppm already matters, write to a temporary name and replace it only after verification:
$ pammasksharpen -sharpness=1.2 -threshold=.02 blurred.ppm /path/to/input.ppm > sharpened.ppm.new
$ pnmfile sharpened.ppm.new
sharpened.ppm.new: PPM raw, 1600 by 1200 maxval 255
$ mv sharpened.ppm.new sharpened.ppm
Warning
The mv step is what actually commits the change, so run it only after checking the image. If the command fails, leave the old file alone and investigate. Remove an unwanted temporary file with rm -- sharpened.ppm.new only once you are certain it is disposable; that removal is irreversible.
Common traps
- Missing magic number. Usually an empty or non-Netpbm input. Check the path and run
pnmfileon both the mask and source. - Dimension or maxval mismatch. The mask was not made from the same image, or the source changed between steps. Recreate
blurred.ppmfrom the current source. - Unexpected speckles. Your threshold is probably too low. Try a modest value such as
.01or.02, then compare at the same display scale. - Lost fine detail or halos. The kernel radius or sharpness is too high. Use a smaller odd kernel, reduce
-sharpness, or both. - Do not run the pipeline as root to solve a file-permission problem. Fix ownership or permissions through your normal administration process, and keep the original image until the result has been checked.
Done means
- Version confirmed. pammasksharpen --version identifies the expected Netpbm installation.
- Mask is valid. The Gaussian kernel and blurred mask are proper Netpbm images.
- Dimensions match. The mask and source have matching dimensions and maxval.
- Output checked with pnmfile and, ideally, an image viewer.
- Source untouched, and no existing output was overwritten before verification.