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