Use Extended Opacity Theory to Blend Netpbm Images

There is no command called extendedopacity, but its formula quietly decides how well you blend two Netpbm images. This guide turns the extendedopacity(5) manpage's maths into a safe workflow: blend two matching images, understand what the fade value means, and recognise when you need extrapolation rather than an ordinary fade. Allow about 20 minutes for a first test, including checking the output.

1. Check the installed Netpbm tools

This guide assumes a Linux system with the netpbm package installed. The local package is Netpbm 11.5.2. The theory page itself was generated from an older Netpbm document, so use the installed command manuals for command-line details.

$ command -v ppmmix pamstretch pamarith
/usr/bin/ppmmix
/usr/bin/pamstretch
/usr/bin/pamarith
$ pamstretch --version 2>&1 | head -n 1
pamstretch: Using libnetpbm from Netpbm Version: Netpbm 11.5.2

If a command is missing, stop at this checkpoint and install Netpbm through your normal package-management process. The examples do not need sudo when the images are in a directory you can read and write.

2. Keep the model visible

For each pixel component, the document describes a weighted blend as out = (1 - alpha) * in0 + alpha * in1. At alpha = 0, the result is the first image. At alpha = 1, it is the second. Values between them interpolate. Values below zero or above one extrapolate: they push away from one input instead of staying between the two.

For example, if one red component is 40 and the other is 200, alpha = 0.25 gives 80. The same calculation applies to green and blue, independently. An extrapolated value of alpha = 1.25 gives 240 for this pair. Real image formats have finite sample ranges, so a result outside the permitted range must be handled deliberately. Silent clipping changes the intended effect.

$ awk 'BEGIN { a=0.25; in0=40; in1=200; print (1-a)*in0+a*in1 }'
80
$ awk 'BEGIN { a=1.25; in0=40; in1=200; print (1-a)*in0+a*in1 }'
240

Checkpoint: you should now be able to predict the direction of an effect. A degenerate black image is a useful reference for brightness, a constant grey image for contrast, and a greyscale version for saturation. A blurred image is a useful reference for sharpening.

3. Make an ordinary cross-fade with ppmmix

For two PPM files with the same dimensions and maximum sample value, ppmmix is the direct command-line test. Its fade factor is restricted to the interval from 0.0 to 1.0, so it performs interpolation, not extrapolation. It mixes brightness values rather than light intensity values.

$ ppmmix 0.25 first.ppm second.ppm > blend-25.ppm
$ file blend-25.ppm
blend-25.ppm: Netpbm image data, size 640 x 480, rawbits, pixmap

Replace the filenames with your own files. Do not assume that a successful command proves the images are comparable. If their dimensions or maxvals differ, ppmmix rejects them. Check both inputs before a batch run:

$ pamfile first.ppm second.ppm
first.ppm: PPM raw, 640 by 480  maxval 255
second.ppm: PPM raw, 640 by 480  maxval 255

The wording from pamfile can vary by release. The dimensions and maxval are the fields that matter here. Keep the original images: shell redirection with > truncates an existing destination before the program starts.

4. Use interpolation for scale-up, not as a general blend

pamstretch applies interpolation between neighbouring pixels while enlarging an image by an integer factor. It is useful when the second image in your mental model is a neighbouring sample, but it does not blend two arbitrary image files. A two-times enlargement:

$ pamstretch 2 small.ppm > large.ppm
$ pamfile small.ppm large.ppm
small.ppm: PPM raw, 320 by 240  maxval 255
large.ppm: PPM raw, 640 by 480  maxval 255

The right and bottom edges have a default treatment that differs from the interior. Use -blackedge to interpolate those edges towards black, or -dropedge to drop one source pixel at those edges. Test the edge choice on a copy when borders matter. The output size can change with -dropedge, so verify it rather than relying on a remembered dimension.

5. Treat extrapolation as a separate implementation

The local extendedopacity(5) document explains why values outside 0.0 to 1.0 are useful, but it does not provide a command or file format for applying them. Do not pass an out-of-range value to ppmmix and expect an extended result: that tool documents only 0.0 through 1.0. Likewise, pamarith performs arithmetic on image samples but clips regular arithmetic results to the valid range, which can erase the overshoot that makes extrapolation useful.

If you need saturation increase, sharpening or contrast expansion, first create the reference image, then use an image-processing program that explicitly supports per-sample floating-point arithmetic and a chosen clipping policy. Work in a linear-light representation where the tool supports it. The manpage warns that blending in gamma-warped space gives inaccurate results, and that clamping a reference image can also change the calculation.

For a quick midpoint check, pamarith -mean can calculate the average of two same-sized images, but it is a numeric operation, not proof that your full extrapolation pipeline is correct:

$ pamarith -mean first.pam second.pam > midpoint.pam
$ pamfile midpoint.pam
midpoint.pam: PAM, 640 by 480  RGB

Before using that example, confirm that both PAM files have the same width and height. If you need to replace an existing output, write to a new path, inspect it, then move it into place. That keeps a failed or visually wrong run from destroying the previous result.

Common traps

Done means