Home / Alt manpages / pgmhist(1)

  • pgmhist(1)
  • User command
  • linux

Read PGM Pixel Distributions with pgmhist

pgmhist prints the grey-value distribution of a PGM image without touching the source file. Use it for a quick median, a set of quantiles, or proof that a file holds samples outside its own header range. The examples use Netpbm 11.5.2 from the installed Debian package netpbm 2:11.05.02-1.1build1.

Allow about ten minutes. You need a shell, the netpbm package and a readable PGM file. Every command here only reads images and prints results, so no elevated privileges are normally needed. Keep the original image regardless: pgmhist is an analysis tool, not a repair tool.

1. Confirm the installed command

Check which executable will run and record the package version before trusting its output in a script:

$ command -v pgmhist
/usr/bin/pgmhist
$ dpkg-query -W -f='${Package} ${Version}\n' netpbm
netpbm 2:11.05.02-1.1build1

The manual page is dated 18 December 2021, while the installed Netpbm library reports version 11.5.2. Everything below was checked against that installed command, so keep the distinction in mind if you move a script to another distribution.

Checkpoint

Run pgmhist --help if you need a nudge on the interface. This build just points you at the manual page rather than printing a full option list.

2. Print the ordinary histogram

Give the command a PGM path. With no quantile option, it prints one row per grey value that actually occurs in the image, plus cumulative percentages:

$ pgmhist /path/to/input.pgm
value  count  b%     w%
-----  -----  ------  ------
    0     12   18.8%    100%
   64     20     50%   81.2%
  255     32    100%   18.8%

The exact rows depend on your image. Value is the PGM sample, count is the number of pixels holding it, and b% and w% are cumulative views from the dark and light ends. Values that never occur are simply left out of this human-oriented view.

PGM stores samples from zero through the file's declared maxval, with a larger value reading as brighter. Never assume an eight-bit image from the file name alone; check the header if the range actually matters to you.

3. Make output safe for a script

Add -machine when another program will consume the result. For a PGM with maxval 15, this prints every possible value, including ones with zero pixels:

$ pgmhist -machine /path/to/input.pgm
0 1
1 2
2 0
3 1
4 0
5 0
6 0
7 2
8 0
9 0
10 0
11 0
12 0
13 0
14 0
15 2

Each line is just two decimal tokens: the grey value, then its pixel count. No labels, no percentages. Values run from zero to maxval in order, which is exactly what makes this form easier to parse than the display meant for people.

PGM can also arrive on standard input, which is useful in a pipeline and avoids an intermediate copy:

$ some-pgm-producing-command | pgmhist -machine
0 0
1 1
2 0
3 0
4 0
5 1

Swap in a command that genuinely emits PGM for some-pgm-producing-command. An arbitrary text stream will not do: the input still needs a valid PGM header and sample data behind it.

Checkpoint

For a histogram feeding automation, check the producer's exit status as well as parsing its output. A stream that merely looks valid is not proof the upstream image operation actually succeeded.

4. Ask for one set of quantiles

Choose at most one of -median, -quartile or -decile. These replace the full histogram rather than adding a section onto it.

$ pgmhist -median /path/to/input.pgm
Median:     3
$ pgmhist -quartile /path/to/input.pgm
Quartiles:
Q    Value
---- -----
 25%     1
 50%     3
 75%     7
100%    15
$ pgmhist -decile /path/to/input.pgm
Deciles:
Q    Value
---  -----
 10%     0
 20%     1
 30%     1

That sample output is trimmed only for readability; -decile actually prints all ten rows. Quantiles are real grey values pulled from the image, not interpolated fractions, which matters if you compare results from small images or use a quantile as a threshold.

For a machine-readable quantile, pair the quantile option with -machine. You get one value per line, in quantile order, with no headings at all:

$ pgmhist -quartile -machine /path/to/input.pgm
1
3
7
15

5. Investigate an invalid sample

Normally the command rejects any sample greater than the PGM header's maxval. A file declaring maxval 5 but actually containing a 7 produces an error and status 1:

$ pgmhist broken.pgm
pgmhist: value out of bounds (7 > 5)
$ printf 'status: %s\n' "$?"
status: 1

-forensic does not make a broken image valid; it is a diagnostic exception that counts the actual samples while ignoring the declared maximum, and reports which values were invalid. It cannot process a grey value above 65535.

$ pgmhist -forensic broken.pgm
value  count  b%     w%
-----  -----  ------  ------
    0      1     50%    100%
-----  -----
    7      1    100%     50%

** Image stream contains invalid sample values (above maxval 5)
Valid sample values:   1 (   50%)
Invalid sample values: 1 (   50%)

The forensic run still exits 0 after producing its diagnostic histogram. Keep the original file and go track down the producer, transfer or conversion step that created the invalid stream. Do not quietly feed the result into a pipeline that assumes valid PGM data.

Common traps

  • Two quantile flags at once. Do not pass more than one of the three; they are alternative output modes, not additive ones.
  • Parsing the human layout. Do not parse the aligned human output when -machine gives you stable two-token rows or one-value quantile rows instead.
  • Missing rows meaning zero. They do not, not in the ordinary histogram: it omits absent values entirely, while machine mode includes every one of them.
  • Confusing maxval with actual brightness. The header defines the possible range; the image may only ever use part of it.
  • Reaching for sudo. Add it only if file permissions genuinely require it. Privilege will not repair malformed image data.

If a file will not open, check the path and read permission first:

$ test -r /path/to/input.pgm && echo readable
readable

If the command reports an invalid sample, keep the failing file for diagnosis and only rerun with -forensic once you understand that its output describes invalid input, not a fix for it.

Done means

  • Command confirmed. You know the installed Netpbm version and executable path.
  • Human output understood. You can read a histogram without mistaking cumulative percentages for counts.
  • Scripts use machine mode. You know -machine includes zero-count values that the human view hides.
  • Quantile chosen. You picked one quantile mode and know its values are samples, not interpolations.
  • Invalid data recognised. You can tell a rejected invalid PGM apart from a forensic diagnostic run.
  • Source untouched. The original image is unchanged and nothing needed elevated privileges.