Read PPM Colour Frequencies with ppmhist
ppmhist counts how many pixels in a PPM image use each exact colour, and reports it as a sorted table. This guide runs a basic histogram, reformats it for scripts, switches colour representations, exports a one-row palette, and covers the forensic mode for images with invalid samples. The examples were checked with Netpbm 11.5.2, packaged here as 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, ppmhist, and a readable PPM file. The normal report only reads the image and writes to standard output: no elevated privileges are needed, and nothing here alters the source image.
1. Check the installed command
Confirm which executable is being used and record its Netpbm version. This is a read-only checkpoint:
$ command -v ppmhist
/usr/bin/ppmhist
$ ppmhist -version
ppmhist: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
ppmhist: Built from source dated 2024-03-31 09:09:47
The version matters here: the summary line at the top of a human report was added in Netpbm 10.82, and since Netpbm 10.88 colours with equal frequency get a stable RGB tie-break order. If your output differs on an older installation, check the version before treating that as an image difference.
2. Generate a basic histogram
Pass the PPM path as the final argument:
$ ppmhist /path/to/image.ppm
Summary: 3 colors: 1 black, 1 white, 0 gray, 1 color
r g b lum count
----- ----- ----- ----- -------
0 0 0 0 3
255 0 0 76 2
255 255 255 255 1
Your rows depend on the image. The report lists red, green and blue sample values, a luminosity value, and the pixel count for that exact colour. The default sort is frequency, most common first, and the displayed component range follows the PPM maxval, so do not assume every file uses 255. The rows are the data to feed into a review or script; the summary is just a quick scan.
3. Make output suitable for a script or comparison
Suppress the headings and summary with -noheader:
$ ppmhist -noheader /path/to/image.ppm > /tmp/image-colours.txt
$ sed -n '1,5p' /tmp/image-colours.txt
0 0 0 0 3
255 0 0 76 2
255 255 255 255 1
This is still whitespace-formatted text, not a CSV or a machine-readable interchange format. Treat the columns as a report, not something to split blindly on a fixed number of spaces.
Use -sort=rgb for a deterministic colour order, low red to high red, then green and blue:
$ ppmhist -sort=rgb -noheader /path/to/image.ppm
Use the full option spelling in scripts. The default frequency order is usually better for finding dominant colours; RGB order is easier to compare against a palette or colour table.
4. Choose a different colour representation
For web or graphics work, hexadecimal components can be more convenient:
$ ppmhist -hexcolor -noheader /path/to/image.ppm
0000 0000 0000 0 3
00ff 0000 0000 76 2
00ff 00ff 00ff 255 1
For calculations, -float scales the components and luminosity into the range 0 to 1:
$ ppmhist -float -sort=rgb -noheader /path/to/image.ppm
0.000 0.000 0.000 0.000 3
1.000 0.000 0.000 0.299 2
Warning
-hexcolor and -float are alternatives. Do not combine either with -map, and do not combine them with each other. The installed command rejects the conflict with an error such as You can specify only one of -hexcolor, -float, and -map.
5. Export a one-row palette
Use -map when another Netpbm program needs a PPM colour map rather than a human report:
$ ppmhist -map /path/to/image.ppm > image-palette.ppm
$ head -5 image-palette.ppm
P3
# color map
3 1
255
#Summary: 3 colors: 1 black, 1 white, 0 gray, 1 color
The result is a genuine plain PPM image, one column per distinct input colour and one row, with the histogram information kept in its comments. Check the magic number and dimensions before passing it on:
$ file image-palette.ppm
image-palette.ppm: Netpbm image data, size = 3 x 1, pixmap, ASCII text
Warning
Redirection with > truncates an existing file before ppmhist runs. If the palette name already exists, write to a new temporary name first, for example image-palette.ppm.new, and only replace the old file after checking it:
$ mv image-palette.ppm.new image-palette.ppm
If the command fails, remove the incomplete .new file and the original stays available. Do not use sudo to write a working-directory palette.
6. Investigate invalid sample values
Normally, ppmhist rejects a PPM sample greater than the file's declared maxval, treating it as a malformed image rather than a harmless variation. Preserve the original and copy it to a disposable working file before investigating.
The -forensic option tells ppmhist to count the actual sample values despite that invalid declaration, and to report the invalid pixels:
$ ppmhist -forensic /path/to/suspect.ppm
... histogram and invalid-pixel diagnostics ...
Warning
Do not treat a forensic histogram as proof the image is valid. It is a diagnostic view of data that violates the PPM declaration. Values above 65535 cannot be processed even with this option, and in the rarely used plain PPM format, a number above that limit can appear where a sample belongs.
This is the point where an image viewer can quietly distract you: it may display something normally while the file remains structurally invalid. Check the declared maxval and the producer that wrote the file before repairing or converting it. Do any actual repair on a copy, never inside this read-only workflow.
7. Diagnose common failures
If the command cannot open the file, check the path and read permission without changing anything:
$ ls -l /path/to/image.ppm
$ test -r /path/to/image.ppm && echo readable
- Unexpected counts? Identical RGB triples are counted together, while two visually similar colours remain separate entries.
- Check the format too. A conversion step before
ppmhistcan change both the samples and the number of distinct colours, and plain versus raw PPM matters here. -colornameadds a dictionary name. An exact match is shown plainly; the nearest dictionary colour is marked with an asterisk. It fails if the dictionary is unavailable, so treat it as a display aid, not a canonical colour identity.
Done means
- Version and path confirmed. You checked the installed Netpbm version and the PPM path.
- Histogram understood. You produced one and know the frequency order, sample scale and count column.
- Format matched the need. You used
-noheader,-sort=rgb,-hexcoloror-floatfor a specific purpose. - Palette exported carefully. You used
-maponly when a one-row PPM palette was required, and verified its dimensions. - Forensic mode used correctly. Reserved for malformed samples, with the original image kept unchanged.
- No privilege overreach. You avoided
sudoand protected existing output files from shell-redirection truncation.