Home / Alt manpages / pamditherbw(1)

  • pamditherbw(1)
  • User command
  • linux

Convert a PGM to Dithered Black and White with pamditherbw

pamditherbw turns a greyscale PGM into clean black and white instead of the mud you get from a plain threshold. That distinction matters most on a one-bit display or a thermal printer. This walkthrough covers the default Floyd-Steinberg run, a repeatable seeded version, four alternative dither methods and the PBM conversion step for older tools. Allow about ten minutes.

You need Netpbm's pamditherbw and pamfile commands and a PGM or greyscale PAM input. The examples write new files in the current directory, need no elevated privileges, and never touch the source image. This guide was checked against Netpbm 11.5.2, packaged as netpbm 2:11.05.02-1.1build1.

1. Check the version and the input

Confirm the binary and version with read-only checks that change nothing:

$ command -v pamditherbw
/usr/bin/pamditherbw
$ pamditherbw --version
pamditherbw: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
...
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

The version line carries build details after the first row. If your output names a different release, check its local manual before trusting the version-specific detail below: the -randomseed option only arrived in Netpbm 10.45.

Checkpoint

Inspect the input before converting it, so you catch a colour file or a broken header without ever creating output.

$ pamfile input.pgm
input.pgm: PGM, 1920 by 1080 by 255

Swap in your own path. pamditherbw expects PGM or a PAM with tuple type GRAYSCALE, but it does not check that promise. Feed it a colour PPM by accident and it takes the first channel as though it were grey, giving you an arbitrary result.

2. Run the default Floyd-Steinberg conversion

With no method flag, pamditherbw uses boustrophedonic Floyd-Steinberg error diffusion, the same thing -fs (an alias for -floyd) selects explicitly. Redirect the result to a new PAM file:

$ pamditherbw -fs input.pgm > output.pam

The output is PAM with tuple type BLACKANDWHITE, not legacy PBM. Verify it before handing it to another program:

$ pamfile output.pam
output.pam: PAM, 1920 by 1080 by 1 maxval 1
    Tuple type: BLACKANDWHITE

Your dimensions will differ. An input error means check the path and header first; a permissions error means pick a directory you can write to. Do not reach for sudo just to solve a local write-permission problem.

3. Make the result repeatable

Floyd-Steinberg and Atkinson both use random numbers while diffusing error. Left alone, the seed comes from the time and process ID, so two runs can differ. Fix that with an integer seed whenever a build, test or comparison needs the same bytes twice:

$ pamditherbw -fs -randomseed=123 input.pgm > output-123.pam
$ pamditherbw -fs -randomseed=123 input.pgm > output-123-again.pam
$ cmp output-123.pam output-123-again.pam
# no output from cmp means the files match

Write the seed as an equals sign followed by an integer. It does nothing for methods that ignore randomness. Note the seed in a script or build log whenever reproducibility matters.

4. Pick a different visual treatment

Only change the quantisation method when the output's look or downstream use calls for it:

  • -threshold makes a hard brightness cut. Good before edge or peak detection, but harsh to look at.
  • -atkinson is another error-diffusion method and often the best-looking result.
  • -dither8 (also -d8) uses a 16 by 16 Bayer ordered-dither matrix.
  • -cluster3, -cluster4, -cluster8 (aliases -c3, -c4, -c8) give clustered-dot patterns with a newspaper look.
  • -hilbert uses Hilbert-curve halftoning, useful for devices that cannot render individual pixels distinctly.

Compare thresholding against Atkinson without overwriting your first result:

$ pamditherbw -threshold input.pgm > threshold.pam
$ pamditherbw -atkinson -randomseed=123 input.pgm > atkinson.pam
$ pamfile threshold.pam atkinson.pam

Abbreviated options work, but full names review better in scripts and stay unambiguous if the option list ever changes.

5. Tune the threshold or the Hilbert clump

-value shifts the threshold used by Floyd-Steinberg, Atkinson and plain thresholding. It must sit between 0 and 1: above 0.5 darkens the image, below 0.5 lightens it.

$ pamditherbw -threshold -value 0.4 input.pgm > lighter.pam
$ pamditherbw -threshold -value 0.6 input.pgm > darker.pam

That is a per-method threshold, not a general brightness correction: it never touches the source image.

For Hilbert dithering, -clump sets how many pixels sit in a clump. Usual range is 2 to 100, default 5. Smaller values smear less and look less grainy, at some cost to greyscale linearity:

$ pamditherbw -hilbert -clump 2 input.pgm > hilbert-small.pam
$ pamfile hilbert-small.pam

Treat this as a visual or printer-specific tweak, not a universal quality knob, and stay inside the documented range: another Netpbm build may accept an out-of-range value differently.

6. Convert to PBM only if an old tool needs it

Keep the PAM output when the next program understands PAM. If an older program insists on PBM, convert the already-checked result with pamtopnm:

$ pamtopnm output-123.pam > output.pbm
$ pamfile output.pbm
output.pbm: PBM, 1920 by 1080

This adds a file rather than replacing one, so both PAM and PBM stay available. Skip the step entirely if the downstream program reads PAM.

Common traps

Warning

Shell redirection replaces an existing destination before pamditherbw even starts, and there is no undo inside the program itself. Before re-running a command, pick a new filename or be sure the old output is disposable; recover a bad result from your normal file-management process or a backup.

A non-zero exit status or a missing output usually means a bad path, unreadable input, invalid image data or an unwritable destination. Fix that, then re-run with a fresh output path. Remember that a clean pamfile check only confirms the container and tuple type, not that the picture is actually right for your purpose.

Done means

  • Version checked. The installed Netpbm version and input type are known.
  • Input verified. The source is PGM or greyscale PAM, not an unverified colour image.
  • Conversion done. A chosen dither method produced PAM with tuple type BLACKANDWHITE.
  • Seed fixed where byte-for-byte repeatability mattered.
  • -value or -clump used only for the method each one affects.
  • PBM conversion skipped unless the next tool actually needs it.