Home / Alt manpages / pamlevels(1)

  • pamlevels(1)
  • User command
  • linux

Adjust Netpbm Image Tones with pamlevels

pamlevels remaps the black and white points of a Netpbm image and writes the result to a new file. The same mechanism stretches to a third point for a quadratic, gamma-like adjustment. Allow about ten minutes if Netpbm is already installed.

This guide uses the installed Netpbm package, version 2:11.05.02-1.1build1 on the machine where it was checked. You need an input image in a format pamlevels can read, permission to read it, and enough space for a new output file. None of the examples need elevated privileges.

1. Check the command and choose a new output path

Confirm the command is available and note the package version:

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

pamlevels reads an image from the named file, or from standard input if none is given, and writes the transformed image to standard output. Redirect that to a new path such as adjusted.ppm. Never redirect over the source unless losing the original is fine: the shell can truncate the destination before the program even reports an error.

Checkpoint

Swap in your own input name below, and pick an output name that is not already holding something you need.

2. Apply a simple black-preserving adjustment

Two mapping pairs define a linear transformation in light intensity. This one keeps black at black and maps a slightly darker white point up to white, brightening the upper part of the tonal range:

$ pamlevels -f1 black -t1 black \
    -f2 white:0.9 -t2 white input.ppm > adjusted.ppm

The long forms are -from1, -to1, -from2 and -to2, and the short forms above are documented abbreviations. At least two full mapping pairs are required. A colour can carry an optional intensity scale after a colon, so white:0.9 means white at 0.9 times its intensity before it gets mapped to the target.

There is no terminal message to read as success or failure here. A zero exit status just means the command finished; the redirected file is the real result, and it needs checking on its own terms:

$ printf 'pamlevels exit status: %s\n' "$?"
pamlevels exit status: 0
$ pamfile adjusted.ppm
adjusted.ppm: Netpbm image data, size 2 x 1, rawbits, pixmap

The exact dimensions and wording from pamfile depend on your own input and Netpbm build. What matters is that the output is recognised as an image, not an empty or unrelated file.

3. Set a white point explicitly

To correct a warm or otherwise uneven white point, map a specific RGB colour to white while keeping black fixed:

$ pamlevels -f1 black -t1 black \
    -f2 rgbi:0.9/0.83/0.80 -t2 white input.ppm > white-point.ppm
$ pamfile white-point.ppm

Netpbm colour specifications can name a colour like black or white, or spell one out as rgbi:0.9/0.83/0.80. Those numbers are brightness values even when the command is running in an intensity-linear mode. Get the channel order and separators exactly right: a typo here is far more likely to fail the parse than to quietly produce a wrong-but-plausible colour.

4. Add a third point only when the curve needs it

A third mapping pair turns the transformation quadratic, which can compress or reshape the middle and upper tones:

$ pamlevels \
    -f1 black -t1 black \
    -f2 white -t2 white \
    -f3 white:0.5 -t3 white:0.6 \
    input.ppm > compressed.ppm
$ pamfile compressed.ppm

This resembles gamma correction, but it is not a general colour-management tool, and three anchors can make an image look worse just as easily as better when they do not describe the curve you actually want. Start with two pairs, look at the result, and only add the third when you can name the reason in terms of input and output points.

5. Choose the intensity model carefully

By default the transformation works in light intensity, while an ordinary PPM is normally brightness, or gamma-adjusted. Use -linear only when the input is already an intensity-linear PPM and you want the output to stay in that form:

$ pamlevels -linear \
    -f1 black -t1 black -f2 white -t2 white \
    linear-input.ppm > linear-output.ppm

This flag does not convert an ordinary image into a physically correct linear one; it requires the input to already be linear and produces linear output in turn. Do not combine -linear with -fitbrightness: the manual says outright that the two cannot be used together, since brightness-fitting is not implemented for the linear mode.

-fitbrightness instead applies the curve in brightness values. It runs faster and matches what a lot of other image tools do, though the manual calls it normally undesirable for having no physical basis. Reach for it only when matching an existing brightness-domain workflow is the actual goal:

$ pamlevels -fitbrightness \
    -f1 black -t1 black -f2 white -t2 white \
    input.ppm > brightness-domain.ppm

6. Recover from a bad result

Keep the original input and compare every output before it goes anywhere near a wider workflow. A wrong result means removing or renaming just the new file and rerunning with a different mapping, never touching the source. If a command fails outright, read its diagnostic and exit status first: adding sudo will not repair a malformed colour specification.

In a script, stop on failure before handing the output to anything else:

if pamlevels -f1 black -t1 black -f2 white -t2 white \
    input.ppm > adjusted.ppm; then
    pamfile adjusted.ppm
else
    status=$?
    printf 'pamlevels failed with status %s\n' "$status" >&2
    exit "$status"
fi

If a redirection left an incomplete file behind after a failure, treat it as disposable and leave the source alone. A successful pamfile check only confirms the file has a valid Netpbm structure, not that the tonal curve actually looks right.

Done means

  • Checked the install. The Netpbm version and pamlevels path are known.
  • Supplied two pairs at least. At least two complete mapping pairs were given.
  • Kept the source. The original is preserved and the output went to a deliberate new path.
  • Verified the result. pamfile recognises the output as a Netpbm image.
  • Matched the intensity model. -linear was used only for intensity-linear PPM, never alongside -fitbrightness.
  • Justified the third point. A third mapping pair was added only when a quadratic curve was actually intended.