1 The idea
“White” isn’t one colour. Daylight (D65) is much bluer than a 3200K tungsten bulb. sRGB uses a D65 white; ACES uses a white near D60, slightly warmer.
Chromatic adaptation moves a whole set of colours from one white to another, a bit like our eyes adjusting to the light. Bradford is a widely used standard method. On the diagram, each line runs from a hollow circle (under the light) to a filled one (after Bradford), showing where each colour moves.
XYZ′ = M⁻¹ · diag(LMS_to / LMS_from) · M · XYZ (M = Bradford)2 Hands-on
Task: under 3200K light, set “adapt from” so the grey card reads neutral
Watch the cyan ring on the diagram; put it on the light’s white
3 Deep dive
Where each white sits
On the xy diagram, whites from hot glowing bodies (bulbs, roughly the sun) line up on a curve called the Planckian locus: low temperatures towards orange, high ones towards blue. D65 and the ACES white are standard whites near that curve, but not exactly on it.
| White | x | y |
|---|---|---|
| D65 (sRGB, Rec.709, P3-D65, Rec.2020) | 0.3127 | 0.3290 |
| ACES (~D60) | 0.32168 | 0.33767 |
| Tungsten 3200K (Planckian, approx.) | 0.4232 | 0.3991 |
What Bradford does
Bradford turns XYZ into three cone-like channels (a sharpened version of the eye’s responses), scales each channel by the ratio of the destination white to the source white, and converts back. The whole set of colours moves together, and the source white lands exactly on the destination white.
- 1XYZ
- 2Bradford → LMS
- 3Scale by white ratio
- 4Back to XYZ
ACEScg ↔ sRGB needs adaptation
ACEScg white (1,1,1) converted to sRGB without adaptation comes out at about (1.05, 1.00, 0.92), a warm yellowish tint. Adapted with Bradford it is exactly (1, 1, 1). ACES configs already include this step (Bradford or CAT02, depending on the config), so convert through the config rather than a hand-typed matrix. The sRGB → AP1 primaries conversion in CS4 already contained this step.
White picks up a tint after a space conversion? Suspect a missing adaptation step
White balance in comp
In comp we rarely adapt the whole plate, because its light colour is the intended mood. But when an element shot under different light joins the shot, say smoke filmed under tungsten going into a daylight scene, its white has to move to the plate’s light before matching black and white points.
4 In real work
In Nuke
- Grade: sample a grey card or something neutral into whitepoint, then set gain to the grey level the card should read (its average, say). That is a per-channel multiply in linear that neutralises without an exposure jump; leave gain at 1 and the card is pushed up to 1.0.
- OCIOColorSpace: convert ACEScg ↔ sRGB through the config, which already contains the adaptation step.
- Colorspace: converts the curve, the white point (illuminant) and the primaries as separate settings.
- ColorMatrix: takes a 3×3 matrix by hand; use it only when you know exactly where the numbers came from.
Common mistakes → the fix
- ✗ Fixing an orange cast by lowering saturation✓ The picture gets dull but stays orange. Move the white instead (per-channel multiply or adaptation).
- ✗ Converting spaces with a matrix that skips adaptation✓ White picks up a tint. Use the config, or a matrix that already includes Bradford/CAT02.
- ✗ Neutralising every shot the same way✓ Light colour is the shot’s mood. Match elements to the plate’s light; don’t scrub the plate.
Before you send the shot
- Elements shot under other light have had their white moved to the plate’s
- Every space conversion goes through the config or includes adaptation
- Neutral objects in the plate and the CG sample close to each other
5 Check yourself
Converting ACEScg to sRGB but skipping chromatic adaptation: what happens to white (1,1,1)?
🔒 Answer the question above and this card opens
1. A grey card under 3200K light, with no white balance, on a D65 screen looks…
2. Why isn’t the ACES white D65?
Where the numbers come from: Colour maths comes from src/figures/colormath.ts (sRGB IEC 61966-2-1, ARRI LogC3 EI 800, sRGB/P3/Rec.2020/ACES AP1 primaries and Bradford, checked against reference numbers). Tungsten 3200K uses the Planckian-locus approximation of Kim et al. (2002). Lighting the plate with another light is simulated with Bradford, a teaching approximation (real light changes each material differently). The goal allows up to 1.5% difference between channels.