Blur and Sharpen Netpbm Images Safely with pnmconvol
pnmconvol applies a convolution matrix to a Netpbm image, which is the plumbing behind a box blur or a sharpen filter. You will apply a small kernel, check the result, and keep the original output safe if the command fails. The examples use Netpbm 11.5.2, installed here from package version 2:11.05.02-1.1build1. Allow about fifteen minutes if you already have a PGM, PPM or PAM image to test.
The route
Jump straight to the step you need, or tick off Done means at the end.
- You need: the
netpbmpackage, a readable input image, and a directory where you can create a new output. - No sudo needed. These operations normally need no elevated privileges; do not use
sudomerely because the command is installed system-wide.
1. Check the installed command
Confirm which executable will run and record its Netpbm version:
$ command -v pnmconvol
/usr/bin/pnmconvol
$ pnmconvol --version
pnmconvol: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
...
The version line is useful when comparing results with another machine. The manual page supplied with this installation is dated 30 November 2018, while the executable is Netpbm 11.5.2, so this guide follows the installed command and its local manual page.
Checkpoint
If command -v finds nothing, stop and install Netpbm through your normal package-management process. Do not copy a binary from an untrusted source.
2. Choose a convolution matrix
A matrix gives each input pixel and its neighbours a weight. Its width and height must be odd, so there is a centre element. A 3 by 3 matrix of ones is a simple box blur; put it in a separate text file with exactly one space between values:
1 1 1
1 1 1
1 1 1
- Save it as a file. A repeatable command should save that as
blur.matrix, with no comments or metadata. - Use exactly one space. Not tabs, not multiple spaces: the manual says each row is separated into elements by exactly one space.
- Match row lengths. The rows must have the same number of elements.
You can put a matrix directly on the command line instead:
$ pnmconvol -normalize -matrix='1,1,1;1,1,1;1,1,1' input.ppm > output.ppm
Keep the quotes. A semicolon normally separates shell commands, so leaving them unquoted can run an unintended command; a matrix file is easier to review and safer to reuse.
3. Apply the blur to a new file
Use -matrixfile to select the file and -normalize to scale the weights so each colour plane sums to one:
$ pnmconvol -matrixfile=blur.matrix -normalize input.ppm > output.ppm
pnmconvol: Convolution is a simple mean horizontally and vertically
The input file may instead come through standard input by omitting the final filename, but naming it explicitly makes a script easier to read. The output goes to standard output, so the shell redirection creates output.ppm. The informational line above is normal for this matrix.
Checkpoint
A successful exit status:
$ printf '%s\n' "$?"
0
Do not confuse -normalize with a resize or a contrast adjustment. It changes the relative scale of the weights used for the convolution: without it, the nine values in the example sum to nine, so the result would be biased brighter.
4. Verify the output image
Inspect the result with a Netpbm-aware tool before replacing anything you care about:
$ pamfile output.ppm
output.ppm: PPM raw, 640 by 480 maxval 255
Your dimensions will differ. Check that the output exists, has the expected format and dimensions, and opens correctly in the viewer or later conversion step you trust. A PGM or PPM output can be passed to another Netpbm program; the command does not create PNG or JPEG output by itself.
Checkpoint
Keep input.ppm untouched until you have checked output.ppm. If the command fails, the input remains available for another attempt.
5. Protect an existing destination
Warning
Shell redirection with > truncates its destination before pnmconvol starts. Never test a new kernel by redirecting straight over a useful image. Write a temporary name, verify it, then replace the old output deliberately:
$ pnmconvol -matrixfile=blur.matrix -normalize input.ppm > output.ppm.new
$ test -s output.ppm.new && pamfile output.ppm.new
output.ppm.new: PPM raw, 640 by 480 maxval 255
$ mv -- output.ppm.new output.ppm
The final mv changes state and replaces output.ppm if it already exists, so run it only after the check passes. If conversion fails, leave the previous output alone and remove the incomplete .new file after inspecting the error. If the old output is valuable, make a backup before the replacement:
$ cp --preserve=all output.ppm output.ppm.backup
Recovery
Restore that backup if the replacement turns out wrong. Deleting it is irreversible, so keep it until the replacement has been reviewed.
6. Understand edges and clipping
At an image edge, where the matrix would extend beyond the input, pnmconvol copies the input pixels directly to the output. That can leave a visible border when a blur or sharpen operation reaches the edge. For a more uniform result, pad the image first, convolve it, then cut the margin away:
$ pnmpad -left=1 -right=1 -top=1 -bottom=1 input.ppm > padded.ppm
$ pnmconvol -matrixfile=blur.matrix -normalize padded.ppm > convolved.ppm
$ pamcut -left=1 -right=-1 -top=1 -bottom=-1 convolved.ppm > output.ppm
This example matches a 3 by 3 matrix. A 5 by 3 matrix would need two pixels on the left and right and one at the top and bottom. The padding and cutting commands are separate from pnmconvol, so verify each intermediate file before using it in a batch job.
Values outside the output format's range are clipped. Negative weights are especially easy to mishandle because Netpbm samples cannot be negative: a sharpen matrix such as -1,3,-1 can produce negative or overly large values, losing information when values are clipped to zero or the image maxval. The -bias option adds a value to each sample before clipping, which can preserve the position of negative results for a later program that understands the bias. It does not make the image automatically correct, so document the bias beside the output.
Common traps
- Matrix rejected: count the values in every row and check for accidental tabs or repeated spaces. Use either
-matrixor-matrixfile, not both, and keep both dimensions odd. - Brightness changed: check whether the weights sum to one, or rerun with
-normalize. Normalisation changes the actual weights, so a matrix chosen for exact numeric output should be calculated explicitly and checked without relying on the convenience option. - Visible border: use the padding workflow above.
- Flat, clipped or dark result: inspect negative weights, the input maxval and any bias. Do not solve a data-range problem by repeatedly increasing arbitrary values; make a small test image and compare the output after each change.
Done means
- Version confirmed. The installed executable and Netpbm version were checked.
- Matrix valid. The matrix has odd dimensions, equal row lengths and deliberate weights.
- Normalisation intentional.
-normalizeis used when preserving average brightness is the goal. - Output verified before replacing. The output was written separately, checked with
pamfile, and only then moved into place. - Edges understood. Edge behaviour, clipping and any bias are understood for the chosen matrix.