Turn Greyscale Images into Black and White with pamthreshold
You will finish with a black-and-white PAM image made from a greyscale PGM or PAM input, plus a way to convert it to PBM when an older tool needs that format. The examples use the installed Netpbm package, version 2:11.05.02-1.1build1, and the behaviour documented by its local pamthreshold(1) manual page.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need the netpbm package, a readable greyscale image, and enough free space for a new output file. These commands normally run as your ordinary user. Do not use sudo unless your input or destination permissions genuinely require it.
1. Check the input and installed command
pamthreshold expects a PGM image or a PAM image with tuple type GRAYSCALE or GRAYSCALE_ALPHA. It does not validate the tuple type, so passing a colour PPM may produce output that is technically written but not useful. Check the command and input before choosing an algorithm:
$ command -v pamthreshold
/usr/bin/pamthreshold
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1
$ file input.pgm
input.pgm: Netpbm image data, size 1200 x 800, rawbits, greymap
The exact file wording varies. The useful checks are that the input exists, is readable, and is a greyscale Netpbm image. Keep the original file: pamthreshold reads it and writes its result to standard output.
Checkpoint
If command -v finds nothing, stop and install Netpbm through your normal package-management process. Do not replace the missing command with a similarly named image utility without checking its format and threshold semantics.
2. Use the default automatic threshold
With no method option, the program calculates a global threshold using its iterative algorithm. Redirect standard output to a new destination, not the input:
$ pamthreshold input.pgm > output.pam
pamthreshold: using global threshold 0.38
The threshold value in the diagnostic is image-dependent. It is written to standard error, while the PAM image goes to standard output. That makes the normal redirection safe for the image data and leaves the diagnostic visible in the terminal.
Check the result's header:
$ sed -n '1,8p' output.pam
P7
WIDTH 1200
HEIGHT 800
DEPTH 1
MAXVAL 1
TUPLTYPE BLACKANDWHITE
ENDHDR
Do not expect a PGM or PBM header here. The documented output is PAM with tuple type BLACKANDWHITE. A successful exit status confirms that the command completed; checking the header also confirms that the result has the expected format and dimensions.
3. Set a fixed threshold for predictable results
Use -simple when you want one global threshold that you choose. The threshold is a floating-point value from 0 to 1, proportional to the input sample range. At the default value of 0.5, pixels at least half as bright as the input maxval become white and darker pixels become black:
$ pamthreshold -simple -threshold=0.5 input.pgm > output-fixed.pam
$ sed -n '1,8p' output-fixed.pam
P7
WIDTH 1200
HEIGHT 800
DEPTH 1
MAXVAL 1
TUPLTYPE BLACKANDWHITE
ENDHDR
The same option can be written with two hyphens or with whitespace instead of the equals sign, for example --simple --threshold 0.5. Spell options in full in scripts so that a future reader does not have to resolve the manual's permitted abbreviations.
Use a lower threshold when faint foreground marks should survive, and a higher one when light background texture is being mistaken for foreground. Test on a new output name each time. Shell redirection with > truncates an existing destination before pamthreshold starts, so it can destroy a useful result if the command then fails.
4. Handle uneven lighting with local thresholding
A single global threshold is a poor fit for a scan or photograph whose background changes across the page. -local=WIDTHxHEIGHT calculates a threshold for each pixel from a centred neighbourhood. For example:
$ pamthreshold -local=31x31 -threshold=0.5 input.pgm > output-local.pam
$ sed -n '1,8p' output-local.pam
P7
WIDTH 1200
HEIGHT 800
DEPTH 1
MAXVAL 1
TUPLTYPE BLACKANDWHITE
ENDHDR
The two numbers describe the neighbourhood, not a resize operation. Larger neighbourhoods can preserve broad regions but may take longer; local processing is generally slower than the default global method. Choose dimensions that match the scale of the marks you want to separate, then inspect the image rather than trusting a visually plausible header.
The -threshold value applies to simple and local thresholding. It has no meaning when you use the default automatic method.
5. Try dual thresholding when contrast varies
-dual=WIDTHxHEIGHT combines a global threshold for low-contrast neighbourhoods with local thresholding elsewhere. This can preserve larger background or foreground areas better than purely local processing:
$ pamthreshold -dual=31x31 -threshold=0.5 -contrast=0.05 input.pgm > output-dual.pam
$ file output-dual.pam
output-dual.pam: Netpbm PAM file
-contrast is also a value from 0 to 1. Its default is 0.05, and it only matters with -dual. Keep the defaults initially, then change one value at a time so that you can tell which setting changed the result.
Checkpoint
Compare the three output files in an image viewer or downstream conversion tool. A command can succeed while the selected neighbourhood is too small, too large, or simply wrong for the image.
6. Convert PAM to PBM only when needed
The PAM result is the native output. If an older program cannot read PAM, or storage matters, pass it to pamtopnm; for a black-and-white image this produces PBM:
$ pamtopnm output-fixed.pam > output-fixed.pbm
$ head -n 1 output-fixed.pbm
P4
The manual notes that PAM can use roughly eight times the space of PBM for this kind of image. Check the converted file before replacing anything downstream. This conversion does not alter either source file.
If the input has an alpha channel, the output is BLACKANDWHITE_ALPHA. Its maxval is 1, so transparency is reduced to fully transparent or fully opaque. The installed manual records alpha handling as available since Netpbm 10.43; do not assume that older Netpbm installations behave the same way.
7. Recover from common mistakes
If the program rejects the input, check the file path, permissions and format without changing the file:
$ test -r input.pgm && echo 'input is readable'
$ file input.pgm
$ head -n 4 input.pgm
If a colour image was supplied, convert it to greyscale with an appropriate Netpbm tool first, then run pamthreshold on that new file. Do not rely on the program's documented lack of input checking to make colour data meaningful.
If an output is wrong, keep the input and earlier output, select a new destination, and rerun with one changed method or value. There is no in-place undo for a redirection that has already truncated a file. Recovery then means restoring that file from a backup or recreating it from the original input. For future runs, write to output.pam.new, verify it, and rename it into place only after the check succeeds.
Done means
- The installed Netpbm version and input format were checked.
- A new PAM file has tuple type
BLACKANDWHITEorBLACKANDWHITE_ALPHA. - The chosen method matches the image: automatic, simple, local, or dual.
- The threshold and contrast defaults were not confused with options that apply to another method.
- PBM conversion was performed only when a consumer required it.
- The original input and useful previous outputs remain recoverable.