Laying one translucent image over another, correctly. Porter and Duff gave compositing an algebra: a per-pixel opacity channel and a set of operators. The one that stacks layers is OVER — and in premultiplied form it is exact, closed, and associative, which is the whole reason the stack composes without seams. Down the center, data flows: two layers go in, the operator blends, the pixel comes out. The blue team builds and defends it; the red team tries to break it.
source Thomas Porter & Tom Duff, Compositing Digital Images, Computer Graphics 18(3), SIGGRAPH 1984, pp. 253–259 — doi:10.1145/800031.808606. Rendered, not quoted.
A pixel is (r,g,b,α). Premultiplied stores colour already scaled by coverage: ĉ = c·α. In that form OVER is a single line:
out = src + dst·(1 − src.α)
applied to every channel, alpha included. The straight form spells the same thing out: out.α = sα + dα(1−sα), colour out.c = (s.c·sα + d.c·dα(1−sα)) / out.α. Same result — premultiplied just drops the divide.
Live premultiplied channels for the current layers:
| r̂ | ĝ | b̂ | α |
|---|
Visibility is decided first: the z-buffer (Catmull, 1974) keeps the nearest opaque fragment. Then comes the compositing step — and translucency is where a single depth number is not enough.
Porter & Duff, 1984, answer it: sort back-to-front and fold with OVER. Premultiplied alpha is the correct algebra because OVER is associative in it — so a sub-tree of layers can be flattened once and re-used, and a filtered/scaled edge stays honest. Each sphere is the next one's premise.
The blue team's live check: recompute the invariants that make OVER correct — opaque identity, transparent identity, and associativity — against known values. If red tampers, this is where it shows.
Every composite needs a source (the layer on top) and a destination (what is already there). Each carries a colour and an alpha — its coverage, from fully transparent (0) to fully opaque (1). Set them below; the panel blends src over dst.
| layer | role | α = 0 | α = 1 |
|---|---|---|---|
| src | on top | invisible | hides dst |
| dst | behind | shows thru | the backing |
Alpha is coverage / opacity, not a colour. That is the term you feed the engine below.
A translucent source disc over the destination, on a checker so coverage is visible. Every pixel is blended live by the OVER operator — never looked up.
What the machine produces, proven: out.α = sα + dα(1−sα), always in [0,1]; an opaque source returns the source untouched; a transparent source returns the destination untouched; and (A over B) over C = A over (B over C) to 1e-9 — the property that lets a whole stack fold safely. The current composite is above; the guarantee is the output.
The blue team's witness (left) confirms these hold live; the red team (right) tries to make them false.
And the numbers must live in linear light. Blend gamma-encoded sRGB directly and edges darken or fringe — physically incorrect, even with perfect algebra. OVER is not the compositor; it is the first proof that layering has a closed, associative form.
"Premultiplied and straight alpha are just two file formats." Cut. Premultiplied is the algebra in which OVER is associative and filtering an edge is correct; straight is a storage convenience that must be converted before blending.
"Alpha means transparency." Corrected. Alpha is coverage — the fraction of the pixel the layer occupies. Porter & Duff model area, not light transmission.
"You can blend straight in sRGB." Kept, flagged. Cheap and common, but it is a gamma error AMBER — correct compositing is done in linear light.
The red team's move: keep the colours straight but feed them into the premultiplied OVER without premultiplying the source — skip the c·α step. Semi-transparent edges then leak the source's full colour: a halo.
Skip the premultiply and the source over-contributes at every partial-coverage pixel — a bright, wrong-coloured fringe around the disc. Transparent-source identity and associativity both break; the witness (window 7) recomputes, disagrees, and turns red. Nothing is faked; the attack is real and it is caught.