System 04 · September 2026

AI colour round trip

Send a plate to an image or video model and get the pixels back in the plate's own colour, with the drift measured, matched and reported inside the comp.

Measured results

  • Drift after the match pass 13.4 → 2.27 codes RMSE An image model on log-look crops regraded them (gain 1.4, contrast up to 2.1). A global matrix fitted on unchanged pixels takes the error to 2.64; the masked residual to 2.27. What remains is re-rendered detail no colour fix removes.
  • Second case 21.1 → 2.85 codes RMSE A video model editing a flat plate with a graded reference image let the reference grade leak into the clip: contrast 1.5, chroma 2.4, blue swinging 50 codes frame to frame.
  • Identity round trip 1 code, max A display-referred plate sent as its own code values and decoded the same way: 1.3e-5 in float, at most one code after 8-bit rounding. Sending it through a display transform instead tone-maps it twice and doubles mid-tone drift.
  • Log encoding null test 0.63% p95 The Slate log shoulder through the shipping nodes over 0.01 to 45 linear, worst 1.01 percent, against a research budget of 4.3 percent. Checked independently against Nuke's own OCIO: forward exactly zero difference.
  • Returns audited 370 files 182 video and 188 still returns. Every video return is limited range; two models return untagged BT.601; one returns HEVC Main10 that Nuke cannot read. Decoding 601 as 709 is worth up to 40 codes on saturated colour.
  • Measured on 45 + 7 still pairs + clips Real pairs from four jobs, then a 176-credit calibration on a colour chart plus plate frames across five image models and two video models, two replicates each.

Problem

Every AI return came back wrong in a way no one could name: a little brighter, cooler, more contrast, sometimes a different matrix altogether. Compositors fixed it by eye, per take, and the fix leaked into the plate around the edit. Nothing recorded what encoding a take had been sent in, so nothing could decode it exactly.

Method

Four separate error sources, each fixed at its own layer. The encoding: display-referred plates go out as their own Camera Rec.709 values and come back through the exact inverse; scene-referred plates go out through a log shoulder with an analytic inverse and a matching clamp, chosen by a null round trip over 0.01 to 45 linear. The file layer: every return is probed, its range and matrix resolved from tags or a per-model table, and converted through a 16-bit chain. The drift: a robust 3x3 matrix plus offset fitted on the unchanged pixels, then a masked low-frequency residual with a luma-range guard. The comp: only the edit region is keymixed over the plate, so grain and highlights stay the plate's own.

In production

The expensive discovery was that no model is pixel-faithful outside the edit, and that the error has three layers: a global colour transform per take (75 to 85 percent of it), a smooth spatial variation of a few codes, and one to two codes of re-rendered detail that no colour operation removes. Only the first two can be fixed, so the pass fixes exactly those and stops. The mask is not optional: an unmasked blur pulls a third to a half of the removed logo back as a ghost. Registration comes first, because returns are 0.2 to 1.9 percent off in scale and up to 18 px off in position.

The calibration run settled the default log encoding on real models rather than on theory, and found the two cases where a different choice wins: one image model on day plates with nothing above about two linear, where the plain display transform is a quarter lower, and a bright cyan phone screen that a matrix fitted on a dark background pushed far off, which is why the correction now fades to identity outside the luma range it was fitted on.

Two bugs in the convert chain were found by measurement rather than by eye: a format that forced an 8-bit intermediate, and a hard-coded matrix that decoded untagged BT.601 returns as 709. Both are fixed, every conversion now writes a decode record next to the frames, and the one delivered take affected was re-converted and re-read.

Next: the per-model override thresholds are unverified, and a regrain stage is still a separate step because the models denoise or sharpen what they touch.