Composite Images with pamcomp, Masks and Opacity
pamcomp drops one Netpbm image on top of another, positions it, and blends it through a transparency mask. This covers doing all three without wiping out a file you actually wanted to keep, using pamcomp from Netpbm 11.5.2, installed here as the Debian package 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 fifteen minutes. You need two readable Netpbm images, such as PPM or PAM files, and a shell. A PGM file is also needed for the masked example. Everything here normally runs as your own user; nothing in this guide needs sudo unless you need elevated access just to read an input or write an output somewhere your user cannot reach.
1. Check the installed command
Start with a read-only version check, so you know which implementation and release you are about to use:
$ pamcomp --version
pamcomp: Using libnetpbm from Netpbm Version: Netpbm 11.5.2
pamcomp: Built from source dated 2024-03-31 09:09:47
pamcomp: Built by Debian
The exact build lines will differ on another host; the useful checkpoint is the Netpbm version. The installed manual describes the command as taking an overlay image, an optional underlying image, and an optional output file. It always writes a PAM image, even when the inputs use other Netpbm formats.
2. Inspect the input files
Confirm the files exist and that a Netpbm reader recognises their dimensions before you compose them:
$ ls -l /path/to/overlay.ppm /path/to/underlying.ppm
$ file /path/to/overlay.ppm /path/to/underlying.ppm
/path/to/overlay.ppm: Netpbm image data, size 640 x 480, pixmap
/path/to/underlying.ppm: Netpbm image data, size 1920 x 1080, pixmap
Replace the paths with real files. The overlay is the image placed on top; the underlying image controls the output dimensions, so differently sized inputs are fine. pamcomp keeps only the part of the overlay that lies over the underlying image. Position it entirely outside the background and it warns you and contributes no pixels at all.
Checkpoint
Make sure the destination is new or already backed up. The output-file argument gets created or truncated before writing starts. Shell redirection is not involved when you give an output path, but the overwrite risk is just as real.
3. Make a solid overlay
Use the simplest form to put an overlay flush with the top-left corner:
$ pamcomp /path/to/overlay.ppm /path/to/underlying.ppm /path/to/composite.pam
$ file /path/to/composite.pam
/path/to/composite.pam: Netpbm image data, size = 1920 x 1080, rawbits, pixmap
Positional order matters: the first file is the overlay, the second the underlying image, the third the output. With no -align or -valign, the overlay starts at the left and top edges. The output dimensions stay those of the underlying image, not the overlay.
There is also a useful default for pipelines: omit the underlying-file argument and it comes from standard input. Do not use standard input for both an image and a mask. This reads the background from a pipe while still naming the overlay and output explicitly:
$ cat /path/to/underlying.ppm | pamcomp /path/to/overlay.ppm - /path/to/composite.pam
Check the exit status after a scripted run:
$ printf 'exit status: %s\n' "$?"
exit status: 0
4. Position the overlay deliberately
Choose a basic horizontal and vertical position, then nudge it in pixels:
$ pamcomp \
-align=center -valign=bottom \
-xoff=-12 -yoff=-24 \
/path/to/overlay.ppm /path/to/underlying.ppm /path/to/composite.pam
The horizontal setting above centres the overlay, the vertical setting anchors it to the bottom, and the negative offsets move it 12 pixels left and 24 pixels up from those basic positions. Positive -xoff moves right; positive -yoff moves down. The full set of horizontal choices is flush left, centred, flush right, just beyond the left edge, and just beyond the right edge. Vertical choices are top, middle, bottom, just above, and just below.
The beyond-frame choices earn their keep mainly with an offset: they let you place an image just outside an edge and slide part of it into view. Do not confuse alignment with resizing; pamcomp never scales the overlay.
5. Add a PGM transparency mask
A mask controls how much of each overlay pixel shows through. It must have the same dimensions as the overlay. White means opaque, black means transparent, grey values give translucency:
$ pamcomp \
-align=center -valign=middle \
-alpha /path/to/overlay-mask.pgm \
/path/to/overlay.ppm /path/to/underlying.ppm /path/to/masked.pam
$ file /path/to/masked.pam
/path/to/masked.pam: Netpbm image data, size = 1920 x 1080, rawbits, pixmap
If the mask dimensions do not match the overlay, stop and fix the mask rather than guessing. Use pamfile if it is installed, or check it with file. The mask is multiplied by whatever you pass to -opacity, whose normal range is 0.0 to 1.0. For a half-strength overlay:
$ pamcomp -alpha /path/to/overlay-mask.pgm -opacity=0.5 \
/path/to/overlay.ppm /path/to/underlying.ppm /path/to/half-strength.pam
-invert reverses the mask sense; it does not touch the separate -opacity value. The program will accept an opacity outside the usual range and clip the resulting samples, but that is an effect, not a safer transparency setting. Keep ordinary compositing between 0.0 and 1.0.
6. Handle alpha channels and colour maths
If the overlay is a PAM image with tuple type RGB_ALPHA or GRAYSCALE_ALPHA, pamcomp can use its own opacity channel. Supply -alpha as well and the two opacities combine. The underlying image decides whether the output gets an opacity channel. By default, the underlying transparency does not alter the colour contribution; add -mixtransparency when you want the two images treated as stacked transparent slides.
Use -linear only when the sample values are proportional to light intensity rather than normal gamma-adjusted PNM or PAM samples. It skips the conversions used for ordinary image data, and applying it casually can shift blended colours. If you are unsure what the inputs represent, leave it out and check the visual result instead.
7. Protect and verify the output
Never test an untrusted composition by overwriting the only copy of something useful. Write to a temporary name, inspect it, then replace the destination only once you have checked it:
$ pamcomp -align=center -valign=middle \
/path/to/overlay.ppm /path/to/underlying.ppm /path/to/composite.pam.new
$ file /path/to/composite.pam.new
$ test -s /path/to/composite.pam.new && echo 'output is non-empty'
output is non-empty
$ mv /path/to/composite.pam.new /path/to/composite.pam
That final mv replaces the old output, so treat it as a deliberate destructive step. If composition fails, leave the original in place and remove only the incomplete .new file once you have checked the error. If you want an undo path, copy the existing destination first:
$ cp --preserve=all /path/to/composite.pam /path/to/composite.pam.bak
Keep that backup until you have opened or converted the new PAM and confirmed its dimensions, position and transparency. A clean exit status proves the command finished; it proves nothing about whether the visual result matches what you actually wanted.
Done means
- Version and inputs checked. You confirmed the installed Netpbm version and identified readable inputs.
- Order correct. You kept the overlay and underlying image in the right positional order.
- Placement deliberate. You set alignment and pixel offsets explicitly when placement mattered.
- Mask matches. Your PGM mask matches the overlay dimensions and uses white for opaque areas.
- Output verified. You confirmed the output is non-empty and has the underlying image's dimensions.
- Replacement backed up. You used a new output name or a backup before any replacement.