Measure Image Regions Precisely with pamgetcolor
You will finish with repeatable colour measurements from a Netpbm image: a single pixel, a labelled set of coordinates, or a circular region with a shared radius. The commands only read the image and print Netpbm colour specifications. Allow about ten minutes. You need a shell, the netpbm package, and a PAM, PPM or another image format that the installed Netpbm readers accept.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide uses Netpbm 11.5.2, installed here as Debian package netpbm 2:11.05.02-1.1build1. The command reports itself as built from source dated 2024-03-31. Other releases can differ, so check the local manual when scripting on another host.
1. Confirm the installed command
Start by checking which executable your shell will run:
$ command -v pamgetcolor
/usr/bin/pamgetcolor
$ pamgetcolor -version 2>&1 | head -4
pamgetcolor: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pamgetcolor: Built from source dated 2024-03-31 09:09:47
pamgetcolor: Built by Debian
pamgetcolor: BSD defined
The version output is diagnostic text, not a measurement. No elevated privileges are needed when the image is readable and the output is going to your terminal. Do not use sudo as a first response to a bad coordinate or an invalid image.
Checkpoint
command -v should return a real path and the library line should identify the Netpbm release you intend to use.
2. Read one pixel
A region is written as column,row. Both coordinates are zero-based: column 0 is the leftmost pixel and row 0 is the top row. The default radius is zero, so the measurement covers one pixel.
$ pamgetcolor 10,14 -infile /path/to/image.ppm
10,14: rgb-255:128/64/32
The exact numbers depend on the image. With the default int format, the components are decimal integers normalised to 255. The output starts with the coordinate, followed by a Netpbm colour specification. If you add a label after a colon, the label replaces the coordinate in the display:
$ pamgetcolor 10,14:sample -infile /path/to/image.ppm
sample: rgb-255:128/64/32
Labels are for identifying output; they do not change the location being measured. Keep labels free of spaces so they remain one shell argument. Quote a label containing shell punctuation.
3. Measure several locations in one run
Pass multiple region arguments after the options. Every region uses the same input image and the same radius:
$ pamgetcolor \
10,10:topleft \
100,100:middle \
200,200:bottomright \
-infile /path/to/image.ppm
topleft: rgb-255:42/18/9
middle: rgb-255:130/131/132
bottomright: rgb-255:240/241/242
The output is one line per region. The sample values above are illustrative output formatting, not a claim about your image. Run the command on a known test image if you need a stable check in a script.
For a small generated test image, standard input avoids creating or overwriting a file:
$ printf 'P3\n1 1\n255\n1 2 3\n' | pamgetcolor 0,0
0,0: rgb-255:1/2/3
If you prefer to make the input explicit, use -infile - for standard input. The ordinary shell pipeline is unprivileged and leaves no image file behind.
4. Average a circular region
Set a positive radius to inspect a circular area around each centre:
$ pamgetcolor -radius 4 100,100:patch -infile /path/to/image.ppm
patch: rgb-255:96/112/138
The radius is measured in pixels and applies to every region in that invocation. A radius of zero is the default single-pixel measurement. The centre must be inside the image, but part of the circle may extend beyond an edge. Only the pixels inside the image contribute to the calculation.
Do not confuse the centre coordinate with a width and height. 100,100 identifies one centre; -radius 4 asks for the circular neighbourhood around it. If you need differently sized regions, run separate commands.
Checkpoint
Confirm the centre is valid before diagnosing the colour result. A coordinate outside the image is rejected:
$ printf 'P3\n1 1\n255\n1 2 3\n' | pamgetcolor 1,0
pamgetcolor: Region at 1,0 is outside the image boundaries.
5. Choose a machine-friendly colour format
The default is int with a maximum value of 255. Use -format when another program needs a different precision or representation:
$ printf 'P3\n1 1\n255\n128 64 32\n' | pamgetcolor -format int:65535 0,0
0,0: rgb-65535:32896/16448/8224
$ printf 'P3\n1 1\n255\n128 64 32\n' | pamgetcolor -format norm:3 0,0
0,0: rgbi:0.502/0.251/0.125
$ printf 'P3\n1 1\n255\n128 64 32\n' | pamgetcolor -format x11:2 0,0
0,0: rgb:80:40:20
The format has the shape format-id:parameter. int uses the parameter as the maximum sample value. norm emits floating-point values normalised to one, with the parameter controlling fractional precision. x11 emits hexadecimal components, with the parameter selecting the number of digits. The parameter is required for these forms even when the default format is already suitable.
If your next tool expects ordinary RGB integers, keep the default. If it expects normalised floating-point input or a fixed-width hexadecimal form, select that format explicitly and test the parser with a known one-pixel image.
6. Use standard input and linear intensity deliberately
Without -infile, pamgetcolor reads the image from standard input. This is useful when another Netpbm command produces the image, or when a small test image is supplied by a shell pipeline:
$ printf 'P3\n1 1\n255\n1 2 3\n' | pamgetcolor 0,0:stdin
stdin: rgb-255:1/2/3
Use the same pattern with a producer you have verified on your machine. Compare the complete output when building a check around it; do not parse a decorative label as if it were a coordinate.
The -linear option tells the program to work with the intensity-linear variation of Netpbm images, where samples represent light intensity rather than brightness. Use it only when that distinction matches the colour-management assumptions of the rest of your workflow. It changes the basis of the calculation; it is not a precision switch and it does not repair an incorrectly tagged or converted source.
7. Handle failures without damaging the source
pamgetcolor does not edit the input image, so there is no rollback operation. The main shell hazard is elsewhere: if you redirect output to a file, > truncates an existing destination before the command runs. Measurements are normally printed to standard output, so inspect them first or choose a new destination:
$ pamgetcolor 10,14 -infile /path/to/image.ppm > /tmp/measurement.txt
$ test -s /tmp/measurement.txt && cat /tmp/measurement.txt
10,14: rgb-255:128/64/32
For an important existing report, write to a new file and replace it only after checking the complete result. If the command fails, remove the incomplete temporary file and keep the original report. That removal is irreversible, so verify the path before using rm.
When a run fails, check the image path and readability, then check the coordinate against the image dimensions. A valid centre does not prove that the requested image is the one you intended. For reproducible automation, capture the exit status and treat any non-zero result as a failed measurement rather than parsing partial output.
Done means
- The command and Netpbm version were confirmed with
command -vand-version. - Coordinates were supplied as zero-based
column,rowvalues inside the image. - Radius zero was used for a pixel, or one shared positive radius was chosen for circular regions.
- Labels identify measurements without changing their coordinates.
- The output format was selected explicitly when a downstream parser requires it.
- The source image was read only, and any redirected report was checked before replacement.