Read PGM Pixel Distributions with pgmhist
You will finish with a repeatable way to inspect the grey-value distribution of a PGM image, extract a median or quantiles, and identify invalid samples without changing the source image. The examples use Netpbm 11.5.2 from the installed Debian package netpbm 2:11.05.02-1.1build1.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell, the netpbm package and a readable PGM file. The commands here only read images and print results. No elevated privileges are normally needed. Keep the original image: 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 relying on 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. The examples below were checked against that installed command. Keep this distinction in mind when moving a script to another distribution.
Checkpoint: run pgmhist --help if you need a reminder of the interface. This build directs the request to the manual page rather than printing a complete option list.
2. Print the ordinary histogram
Give the command a PGM path. With no quantile option, it prints one row for each grey value that occurs in the image, together with 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 the image. The value is the PGM sample, and count is the number of pixels with that value. The b% and w% columns are cumulative views from the dark and light ends. Values that do not occur are omitted from this human-oriented output.
PGM stores samples from zero through the file's declared maxval. A larger value is brighter in the usual PGM interpretation. Do not infer an eight-bit image from the file name: inspect the header if the range matters.
3. Make output safe for a script
Add -machine when another program will consume the result. For a PGM with maxval 15, the command prints every possible value, including values 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 has two decimal tokens: the grey value followed by its pixel count. There are no labels or percentages. The values are ordered from zero to maxval, which makes this form easier to parse than the display intended for people.
PGM can also arrive on standard input. This is useful in a pipeline and avoids creating an intermediate copy:
$ some-pgm-producing-command | pgmhist -machine
0 0
1 1
2 0
3 0
4 0
5 1
Replace some-pgm-producing-command with a command that really emits PGM. Do not use an arbitrary text stream: the input still needs a valid PGM header and sample data.
Checkpoint: for a histogram used in automation, check the producer's exit status as well as parsing its output. A syntactically valid-looking stream is not evidence that the upstream image operation succeeded.
4. Ask for one set of quantiles
You may choose at most one of -median, -quartile or -decile. These options replace the full histogram rather than adding a section to 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
The sample output is shortened only to keep the example readable; -decile prints all ten rows. Quantiles are actual grey values found in the image, not interpolated fractions. That matters when you compare results from small images or use a quantile as a threshold.
For a machine-readable quantile, combine the quantile option with -machine. The result is one value per line, in quantile order, without headings:
$ pgmhist -quartile -machine /path/to/input.pgm
1
3
7
15
5. Investigate an invalid sample
Normally the command rejects a sample greater than the PGM header's maxval. For example, a file declaring maxval 5 but containing 7 produces an error and status 1:
$ pgmhist broken.pgm
pgmhist: value out of bounds (7 > 5)
$ printf 'status: %s\n' "$?"
status: 1
Do not treat -forensic as a way to make the image valid. It is a diagnostic exception that counts actual samples while disregarding the declared maximum, and reports the invalid values. 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 returns status 0 after producing its diagnostic histogram. Preserve the original file and investigate the producer, transfer or conversion step that created the invalid stream. Do not silently feed the result into an image-processing workflow that assumes valid PGM data.
6. Avoid the common traps
- Do not pass more than one of the three quantile options. They are alternative output modes.
- Do not parse the aligned human output when
-machinegives you stable two-token rows or one-value quantile rows. - Do not assume missing rows mean zero pixels. The ordinary histogram omits absent values; machine mode includes them.
- Do not confuse a declared
maxvalwith the brightest value actually used. The header defines the possible range, while the image may use only part of it. - Do not add
sudounless file permissions genuinely require it. Privilege does not repair malformed image data.
If a file cannot be opened, first check the path and read permission:
$ test -r /path/to/input.pgm && echo readable
readable
If the command reports an invalid sample, keep the failing file for diagnosis and rerun with -forensic only when you understand that the output describes invalid input.
Done means
- You confirmed the installed Netpbm version and executable path.
- You can read a human histogram without mistaking cumulative percentages for counts.
- You use
-machinefor scripts and know that it includes zero-count values. - You selected one quantile mode and know its values are samples from the image.
- You can distinguish a rejected invalid PGM from a forensic diagnostic run.
- The source image remains untouched and no command needed elevated privileges.