Home / Alt manpages / pamfunc(1)

  • pamfunc(1)
  • User command
  • linux

Adjust Netpbm Image Values Safely with pamfunc

By the end of this guide, you will be able to apply a repeatable brightness change, clamp samples to a range, or edit bit fields in a Netpbm image with pamfunc. The examples use Netpbm 11.5.2, installed from Debian's netpbm package. Allow about 10 minutes if you already have a PGM, PPM or PAM file to test.

Before you start

You need a shell, the pamfunc command, and a Netpbm image. Check the installed version and command path first:

command -v pamfunc
pamfunc -version 2>&1 | sed -n '1,2p'

On the system used for this guide, the second command reports Netpbm Version 11.5.2. The manpage is dated 9 September 2020, while the installed binary identifies itself separately. If your package is older, check its local manpage before relying on newer options such as -changemaxval.

Checkpoint

You have a readable input image and know where the result will be written. The command writes the transformed image to standard output, so redirect it to a new file while testing. Do not redirect over your only copy.

Step 1: apply one arithmetic function

Choose exactly one transfer function. For ordinary image adjustments, the useful starting points are -multiplier, -divisor, -adder, -subtractor, -min and -max. This example doubles the normalised sample values and saves a new PGM:

pamfunc -multiplier=2 input.pgm > brighter.pgm

The multiplier must be non-negative. Results above the normalised maximum of 1 are clipped, so a value already at full brightness stays there. To darken by half, use the equivalent divisor:

pamfunc -divisor=2 input.pgm > darker.pgm

For a fixed shift, the integer is measured in samples relative to the input image's maxval. With an input maxval of 100, -adder=10 adds 0.1 to each normalised sample. Values are clipped at both zero and one:

pamfunc -adder=10 input.pgm > lifted.pgm
pamfunc -subtractor=10 input.pgm > lowered.pgm

Checkpoint

Inspect the result rather than trusting the filename. Netpbm's pnmtoplainpnm converts a PGM or PPM result to readable text:

pnmtoplainpnm brighter.pgm | sed -n '1,8p'

For a two-by-two PGM with maxval 100 and samples 0 25 50 100, doubling produces samples 0 50 100 100. The image type and dimensions remain PGM and two by two. A malformed or unsupported input normally causes an error, so keep the shell's exit status when checking a pipeline:

set -o pipefail
if pamfunc -multiplier=2 input.pgm > brighter.pgm; then
    pnmtoplainpnm brighter.pgm | sed -n '1,8p'
else
    printf '%s\n' 'pamfunc did not produce a trusted result' >&2
fi

Step 2: clamp without changing contrast

Use -min to raise a floor or -max to impose a ceiling. Their arguments are whole sample values, not percentages. This raises every sample below 20 to 20 and caps every sample above 240 at 240 when the input maxval is 255:

pamfunc -min=20 input.pgm > floor.pgm
pamfunc -max=240 input.pgm > ceiling.pgm

These operations do not stretch the remaining range. They only replace samples outside the requested boundary. The argument is compared with the input maxval, so check it before choosing a number:

pnmtoplainpnm input.pgm | sed -n '1,6p'

Step 3: preserve precision when reducing values

By default, pamfunc keeps the input maxval and rounds the transformed samples into that range. For a division by one or more, -changemaxval can instead change the output maxval and leave sample values scaled with greater precision:

pamfunc -divisor=2 -changemaxval input.pgm > precise-half.pgm
pnmtoplainpnm precise-half.pgm | sed -n '1,6p'

For an input maxval of 100, the verified example reports an output maxval of 200 while samples such as 50 remain 50. Their normalised brightness is therefore halved. This option is not guaranteed to use the changed-maxval method for every operation, and Netpbm formats cap maxval at 65535. If another program expects the original maxval, omit the option and accept the normal rounding.

Step 4: use bit masks only on bit-shaped data

The mask and shift functions treat each sample as a bit string. In this mode, maxval must be one less than a power of two, such as 15 or 255. The mask must fit within that width. This keeps the low four bits of a 4-bit sample:

pamfunc -andmask=0f bits.pgm > low-nibble.pgm
pnmtoplainpnm low-nibble.pgm | sed -n '1,6p'

For samples 0 5 10 15 with maxval 15, the result is the same sequence because every sample already fits the mask. A wider mask, or a shift count greater than the bit width, is an error. Use -ormask to set bits, -xormask to toggle them, -not to invert them, and -shiftleft or -shiftright to move them. Do not use these as a substitute for normal brightness adjustment.

Common traps and recovery

  • PBM black and white values can look backwards. pamfunc operates on the PAM equivalent, where black is 0 and white is 1, regardless of PBM's on-disk convention.
  • Do not combine arithmetic and bit-string assumptions. Arithmetic arguments use normalised samples; masks use the maxval as a bit width.
  • Do not overwrite the source until you have checked dimensions, format and sample values. If a result is wrong, the recovery is simply to discard the new output and rerun the command from the unchanged source.
  • When feeding a pipeline, redirect the final image to a temporary filename and inspect it before renaming it into place. No elevated privileges are required unless your chosen destination is not writable by your user.

Done means

  • The command and package version were checked.
  • One verified function was selected for the required change.
  • The result was written to a new file and inspected with pnmtoplainpnm.
  • The input maxval was considered, especially for -changemaxval and bit masks.
  • The original file remains available for recovery.