Create and Use PBM Masks Safely with pbmmask
Compositing two images means telling Netpbm exactly where one stops and the other starts, and that is what pbmmask is for. You will finish with a PBM mask that is white over an object's figure and black over its background, ready for a paste or arithmetic operation.
The route
Jump straight to the step you need, or tick off Done means at the end.
The examples use pbmmask from Netpbm 11.5.2, installed here as package version 2:11.05.02-1.1build1. Allow about fifteen minutes. You need a shell, the Netpbm tools, and a PBM input image.
The commands read and write files in your working directory and normally need no elevated privileges. This guide does not change system configuration or install anything.
1. Check the installed command
Confirm which executable will run and note the local Netpbm version. This is an ordinary, read-only check:
$ command -v pbmmask
/usr/bin/pbmmask
$ pbmmask --version 2>&1 | head -n 2
pbmmask: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pbmmask: Built from source dated 2024-03-31 09:09:47
The command accepts an optional PBM file; with none given it reads PBM data from standard input, so it slots into a pipeline just as well. Output is another PBM image on standard output, so keep diagnostics on standard error when you redirect that output.
Checkpoint
If command -v finds nothing, stop and install Netpbm through your normal package-management process. Do not work around a missing command with an unverified download.
2. Make a small test image
Before you risk a valuable image, test the behaviour with a tiny ASCII PBM. In PBM, 0 is white and 1 is black; this seven-by-seven sample has a black cross on a white background:
$ cat > cross.pbm <<'EOF'
P1
7 7
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 1 1 1 0 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
EOF
$ file cross.pbm
cross.pbm: Netpbm image data, size = 7 x 7, bitmap, ASCII text
That here-document replaces an existing cross.pbm, so if that name already matters to you, pick a new one or copy the file first. This is the only file-changing step so far.
3. Create the mask without destroying an existing output
Run pbmmask and redirect its output to a new filename:
$ pbmmask cross.pbm > cross-mask.pbm
$ printf 'exit status: %s\n' "$?"
exit status: 0
$ pnmnoraw cross-mask.pbm
P1
7 7
0000000
0000000
0001000
0011100
0001000
0000000
0000000
The mask shown has 1 over the cross and 0 everywhere else. pbmmask works out automatically which input colour is the background, then emits white for that background and black for the figure, so the mask follows the object rather than blindly assuming the input background is white.
Checkpoint
Verify the dimensions and format before you pass the mask to another command:
$ file cross-mask.pbm
cross-mask.pbm: Netpbm image data, size = 7 x 7, rawbits, bitmap
Normal output is raw PBM, which is compact binary data. pnmnoraw above is only there to make the pixels readable in a terminal; it does not touch the original mask unless you redirect its output somewhere.
4. Add a one-pixel expansion when needed
Use -expand when the mask needs to extend one pixel out from the figure, which can give a small white border around an image in the mask workflow:
$ pbmmask -expand cross.pbm > cross-mask-expanded.pbm
$ pnmnoraw cross-mask-expanded.pbm
P1
7 7
0000000
0011100
0111110
0111110
0111110
0011100
0000000
Compare that against the unexpanded result: the shape grows outwards by one pixel where space is available, but it cannot grow past the image edges. Do not add -expand on autopilot, since it changes the mask boundary and can make an object overlap nearby content.
Generated a wrong mask? Recovery is simple: the source PBM is still untouched, so just regenerate the output under a different destination name. Remove an unneeded test output only after checking it is not needed elsewhere; there is no persistent setting to undo here.
5. Use the mask in a black-background paste
For an object whose background is black, the manual gives this two-stage paste pattern. Replace the placeholder coordinates with the destination position:
$ pbmmask object.pbm > object-mask.pbm
$ pnmpaste -and destination.pbm object-mask.pbm X Y \
| pnmpaste -or object.pbm X Y > composed.pbm
$ file composed.pbm
composed.pbm: Netpbm image data, size = ..., bitmap
The first paste keeps the destination wherever the object mask is black; the second pastes the object wherever its figure belongs. Both are ordinary file-processing operations, but > composed.pbm truncates an existing file before the pipeline even completes, so use a new name or a temporary file, inspect it, then replace the old result on purpose.
For an object with a white background, invert the mask and build a black-background copy of the object before running the same paste pattern:
$ pbmmask object.pbm > object-mask.pbm
$ pnminvert object-mask.pbm | pnmpaste -and object.pbm 0 0 > blackback.pbm
$ pnmpaste -and destination.pbm object-mask.pbm X Y \
| pnmpaste -or blackback.pbm X Y > composed.pbm
Keep each intermediate file until you have checked the final image. If a command fails, preserve the original input and inspect the error before retrying.
6. Diagnose the common failures
A non-zero status and a complaint about a bad magic number usually mean the input is not PBM, or not a supported Netpbm image at all. Check the file without changing it:
$ file /path/to/input.pbm
$ head -n 3 /path/to/input.pbm
P1
7 7
A valid ASCII PBM starts with P1; raw PBM uses P4. If the file turns out to be a PNG, JPEG or something else entirely, convert it with the right Netpbm tool first: renaming a non-PBM file does not change its contents.
If the figure gets treated as background, look at the image's border and dominant colour. Background detection is automatic, so an unusual image with no clear background can produce a mask that is technically valid but visually useless. Test a representative file and view the result before running it across a whole batch.
pbmmask is described as probably superseded by pambackground. That does not make the tested command invalid for an existing PBM workflow, but it is a useful boundary: for new background-segmentation work, compare the newer tool's behaviour and output format before you silently swap out a working pipeline.
Done means
- pbmmask resolves to the intended Netpbm installation, version known.
- The input is a readable PBM, and the mask has the expected dimensions.
- The mask's black figure and white background were checked with a readable conversion or image viewer.
- -expand was used only when a wider boundary was actually wanted.
- Paste intermediates used new filenames, so a failed command could not destroy the previous result.
- No system configuration, service or privileged resource was touched.