From f14176de29a97387563ad5c73196b7bfe65b58c6 Mon Sep 17 00:00:00 2001 From: Duncan Tourolle Date: Wed, 26 Aug 2026 17:41:34 +0200 Subject: [PATCH] Give the projector lamp a name instead of a warning Every bake of a Vision3 stock logged: unknown illuminant "K75P", falling back to D55 K75P is a cinema xenon short-arc lamp, and Kodak 2383 and 2393 -- the projection print films those stocks print onto -- name it as the light their result is looked at under. It was never implemented, so it fell through to the unknown branch. The fallback was the right family: a xenon arc sits near 6000 K, close to daylight and nothing like the tungsten enlarger above it. So the pixels do not move. What changes is that D55 is now a documented choice rather than the consolation prize for an unrecognised string, with the approximation stated -- an arc has line structure a Planckian curve cannot express, and the residue of that is small here because the viewing step adapts the white point out either way. The test is the point of the commit. A profile naming a light nobody implemented should fail the suite, not whisper into a log that only gets read when somebody happens to be looking for something else -- which is how this was found. Co-Authored-By: Claude Opus 5 --- core/dr-film/src/spectrum.rs | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/core/dr-film/src/spectrum.rs b/core/dr-film/src/spectrum.rs index 3a432ea..0ac8a44 100644 --- a/core/dr-film/src/spectrum.rs +++ b/core/dr-film/src/spectrum.rs @@ -58,6 +58,18 @@ pub fn illuminant(name: &str) -> Spectrum { // the filter's effect is a colour shift, and a colour shift ahead of // the balance step is by construction invisible. "TH-KG3" | "TH-KG3-L" | "T" => blackbody(3400.0), + // A cinema projector's xenon short-arc lamp, which is what a release + // print is *looked at* under — Kodak 2383 and 2393 name it. + // + // Approximated by D55, and named here rather than left to fall through + // to the unknown branch, which logged a warning on every bake of a + // Vision3 stock and implied something was broken. A xenon arc sits near + // 6000 K, close to daylight and nothing like the tungsten above, so + // daylight is the right family to stand in for it. It is not a + // blackbody — the arc has line structure a Planckian curve has no way + // to express — and the residue of that is small here because the + // viewing step adapts the white point out either way. + "K75P" => ILLUMINANT_D55, other => { if let Some(kelvin) = other.strip_prefix("BB").and_then(|k| k.parse::().ok()) { return blackbody(kelvin); @@ -216,6 +228,21 @@ mod tests { } } + #[test] + fn every_illuminant_a_shipped_profile_names_is_known() { + // The warning that found this said "unknown illuminant K75P, falling + // back to D55" on every bake of a Vision3 stock. The fallback was + // reasonable and the silence was not: a profile naming a light nobody + // implemented should be a failing test rather than a line in a log. + for name in ["D50", "D55", "D65", "TH-KG3", "TH-KG3-L", "T", "K75P"] { + let rgb = Viewing::new(name).to_srgb(&[1.0; SPECTRUM]); + assert!( + rgb.iter().all(|c| (c - 1.0).abs() < 0.01), + "{name} is not a working illuminant: clear frame gave {rgb:?}" + ); + } + } + #[test] fn a_hotter_blackbody_is_bluer() { // Cheap, but it is the one property that catches Planck's law written