Render raws through the DNG reference curve by default, at contrast 1.5
Decides D21 by measurement. The photo gallery holds Lightroom 6 exports of raws in the library, each carrying its Camera Raw settings; clustered by those settings, 663 had no look applied. On 60 of them with their raws, a third held out, the held-out MSE against Lightroom's JPEG was about 1200 for 0.20.0's sigmoid (0.7 EV darker and flatter), 224 for the DNG reference curve after baseline exposure, and about 140 once its input is bent by 1.5/1.4 about grey. So the curve choice defaults to the DNG reference, keeping its index (sidecars record it), and the default contrast is 1.5. Contrast under the DNG reference curve is now a power relative to REFERENCE_CONTRAST (1.4), where the table is untouched; the sigmoid at that contrast still matches the retired base curve. JPEGs are unaffected: the view transform skips a rendered source.
This commit is contained in:
@@ -19,7 +19,7 @@
|
||||
//! shader to it.
|
||||
|
||||
use crate::ops::camera_profile::{mul, working_prophoto};
|
||||
use crate::view::{DEFAULT_CONTRAST, DEFAULT_WHITE, SCENE_GREY};
|
||||
use crate::view::{DEFAULT_CONTRAST, DEFAULT_WHITE, REFERENCE_CONTRAST, SCENE_GREY};
|
||||
|
||||
/// The input scale for a white point: 1 at the default, so sensor white is
|
||||
/// display white as in the SDK's reference; each stop of `white` above it halves the
|
||||
@@ -28,10 +28,14 @@ pub fn input_scale(white: f32) -> f32 {
|
||||
(DEFAULT_WHITE - white).exp2()
|
||||
}
|
||||
|
||||
/// The power the input is bent by about middle grey: 1 at the default
|
||||
/// contrast, so the curve is the reference's untouched.
|
||||
/// The power the input is bent by about middle grey: 1 at
|
||||
/// [`REFERENCE_CONTRAST`], where the curve is the reference's untouched.
|
||||
///
|
||||
/// The default contrast sits above it, so a photograph out of the camera is
|
||||
/// bent by `DEFAULT_CONTRAST / REFERENCE_CONTRAST` — the extra contrast
|
||||
/// Lightroom's exports showed over the bare reference curve (D21 addendum).
|
||||
pub fn contrast_power(contrast: f32) -> f32 {
|
||||
contrast / DEFAULT_CONTRAST
|
||||
contrast / REFERENCE_CONTRAST
|
||||
}
|
||||
|
||||
/// The curve, its scale and its contrast applied to one ProPhoto colour.
|
||||
@@ -103,15 +107,23 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn at_its_defaults_the_input_is_untouched() {
|
||||
fn at_the_reference_the_input_is_untouched() {
|
||||
assert_eq!(input_scale(DEFAULT_WHITE), 1.0);
|
||||
assert_eq!(contrast_power(DEFAULT_CONTRAST), 1.0);
|
||||
assert_eq!(contrast_power(REFERENCE_CONTRAST), 1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_default_adds_the_contrast_lightroom_showed() {
|
||||
// Fitted on Lightroom exports with neutral settings (D21 addendum):
|
||||
// the bare reference curve is a little flat against them.
|
||||
let p = contrast_power(DEFAULT_CONTRAST);
|
||||
assert!((1.05..1.12).contains(&p), "{p}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn grey_goes_through_the_curve_and_stays_grey() {
|
||||
for v in [0.02, 0.13, 0.5] {
|
||||
let out = apply_reference(&ACR3_DEFAULT, [v; 3], DEFAULT_CONTRAST, DEFAULT_WHITE);
|
||||
let out = apply_reference(&ACR3_DEFAULT, [v; 3], REFERENCE_CONTRAST, DEFAULT_WHITE);
|
||||
let want = evaluate(&ACR3_DEFAULT, v);
|
||||
assert!(
|
||||
out.iter().all(|o| (o - want).abs() < 1e-4),
|
||||
@@ -123,7 +135,7 @@ mod tests {
|
||||
#[test]
|
||||
fn an_identity_curve_changes_nothing_inside_the_range() {
|
||||
let c = [0.4, 0.2, 0.1];
|
||||
let out = apply_reference(&identity(), c, DEFAULT_CONTRAST, DEFAULT_WHITE);
|
||||
let out = apply_reference(&identity(), c, REFERENCE_CONTRAST, DEFAULT_WHITE);
|
||||
assert!(
|
||||
out.iter().zip(c).all(|(o, c)| (o - c).abs() < 1e-4),
|
||||
"{out:?}"
|
||||
|
||||
Reference in New Issue
Block a user