Call the reference curve what it is, and drop wording that reads as copying

The view transform's second curve is the DNG SDK's published reference
rendering — the ACR3 default curve applied by RefBaselineRGBTone — so
it is the "DNG Reference" curve in the panel, D21 and the code, not a
name borrowed from another product. Comments and docs that justified a
choice by another editor doing it ("as their Amount", "so a
photographer arriving from it finds the name") now give the actual
reason. The Vivid presets no longer describe themselves as reaching
for another editor's look; they are DarkRoom's own.

Factual mentions stay: which program wrote the library's DNGs, what
was measured against, and preset import. camera-profiles.md gains §15,
on starting a photograph from the edit it already carries.
This commit is contained in:
2026-10-03 14:22:49 -04:00
parent e12783da9f
commit 8294e6b59f
12 changed files with 68 additions and 52 deletions
+10 -10
View File
@@ -1,16 +1,16 @@
//! TRACES: FR-DEV-3j | FR-DEV-3e
//! Camera Raw's tone, as a rendering the view transform can choose (D21).
//! The DNG SDK's reference tone, as a rendering the view transform can
//! choose (D21).
//!
//! Lightroom's colour is mostly its tone curve (camera-profiles.md §1): the
//! The DNG specification's reference rendering runs a raw through the
//! profile's `ProfileToneCurve`, or the ACR3 default for a profile with none.
//! Half of what the curve does is *how* it is applied. Camera Raw's
//! Half of what the curve does is *how* it is applied. The SDK's
//! `RefBaselineRGBTone` runs it on the largest and the smallest channel, and
//! places the middle channel at the fraction between them it had before. Hue
//! is kept; saturation rises wherever the curve is steeper than the
//! diagonal, which for the ACR3 curve is the shadows and the midtones —
//! where Adobe Standard's look table desaturated to compensate.
//! diagonal, which for the ACR3 curve is the shadows and the midtones.
//!
//! It runs in linear ProPhoto, as Camera Raw does, on values clipped to
//! It runs in linear ProPhoto, as the SDK does, on values clipped to
//! `[0, 1]`; its output is linear and goes to the output transform as the
//! sigmoid's does. The curve is read from the profile buffer
//! (`ops::camera_profile::profile_buffer`), which always carries one.
@@ -22,14 +22,14 @@ use crate::ops::camera_profile::{mul, working_prophoto};
use crate::view::{DEFAULT_CONTRAST, DEFAULT_WHITE, SCENE_GREY};
/// The input scale for a white point: 1 at the default, so sensor white is
/// display white as in Camera Raw; each stop of `white` above it halves the
/// display white as in the SDK's reference; each stop of `white` above it halves the
/// input.
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 Camera Raw's untouched.
/// contrast, so the curve is the reference's untouched.
pub fn contrast_power(contrast: f32) -> f32 {
contrast / DEFAULT_CONTRAST
}
@@ -50,7 +50,7 @@ fn rgb_tone(curve: &[f32], p: [f32; 3]) -> [f32; 3] {
}
/// TRACES: FR-DEV-3j
/// The view transform's Camera Raw rendering of one working-space colour.
/// The view transform's DNG reference rendering of one working-space colour.
pub fn apply_reference(curve: &[f32], c: [f32; 3], contrast: f32, white: f32) -> [f32; 3] {
let (to, back) = working_prophoto();
let scale = input_scale(white);
@@ -73,7 +73,7 @@ fn camera_raw_curve(x: f32) -> f32 {
return mix(profile_table[base + i].x, profile_table[base + i + 1u].x, s - f32(i));
}
// Camera Raw's RGBTone: the curve on the largest and smallest channel, the
// The SDK's RGBTone: the curve on the largest and smallest channel, the
// middle one kept at its fraction between them, so hue survives.
fn camera_raw_tone(c: vec3<f32>, scale: f32, power: f32, grey: f32) -> vec3<f32> {
var p = PROFILE_FROM_WORKING * c * scale;
+4 -4
View File
@@ -48,7 +48,7 @@ pub const LOOK: ParamId = ParamId("look");
/// The look's strength at which the LookTable is applied as the profile
/// states it, in percent.
pub const DEFAULT_LOOK: f32 = 100.0;
/// Twice the profile's look: Lightroom's *Amount* reaches the same.
/// Twice the profile's look.
pub const MAX_LOOK: f32 = 200.0;
/// Entries of the buffer's header, before the entries themselves: one
@@ -130,7 +130,7 @@ fn wgsl_mat(m: &[f32; 9]) -> String {
/// The working space to ProPhoto and back, as WGSL constants, and where
/// the profile buffer's sections begin. A helper of its own because the
/// view transform's Camera Raw curve needs it too, and helpers are emitted
/// view transform's DNG reference curve needs it too, and helpers are emitted
/// once each, in the order first asked for.
pub(crate) static PROPHOTO_HELPER: LazyLock<Helper> = LazyLock::new(|| {
let (to, back) = working_prophoto();
@@ -390,7 +390,7 @@ if (hue_sat_dims.x > 0.0 || look_dims.x > 0.0) {
/// The curve is always there: the profile's own where it has one, Camera
/// Raw's ACR3 default otherwise — including in the placeholder every source
/// without a profile binds, whose tables are absent, so a raw with no
/// profile still renders through Camera Raw's tone (D21).
/// profile still has the reference tone curve when it is chosen (D21).
pub fn profile_buffer(tables: Option<&ProfileTables>) -> Vec<[f32; 4]> {
let header = |t: Option<&HueSatTable>| match t {
Some(t) => [
@@ -706,7 +706,7 @@ mod tests {
fn the_buffer_puts_the_header_first_and_the_look_after_the_hue_sat_map() {
let bare = profile_buffer(None);
assert_eq!(bare[..2], [[0.0; 4]; 2], "no tables");
assert_eq!(bare[2][0], 1025.0, "and Camera Raw's default curve");
assert_eq!(bare[2][0], 1025.0, "and the reference default curve");
assert_eq!(bare.len(), HEADER_ENTRIES + 1025);
let t = tables(
Some(uniform(2, 2, 1, [1.0, 2.0, 3.0])),
+2 -2
View File
@@ -36,7 +36,7 @@ pub const WHITE: ParamId = ParamId("white");
/// TRACES: FR-DEV-3j
/// Which curve renders: D19's sigmoid (index 0, the default) or Camera
/// Raw's (D21). Which of the two should be the default is open — the
/// Lightroom-matching work decides it — so the default is what 0.20.0
/// measurement work decides it — so the default is what 0.20.0
/// rendered.
pub const CURVE: ParamId = ParamId("curve");
@@ -161,7 +161,7 @@ impl Operation for ViewTransform {
"\
// Skipped for an already-rendered source: a JPEG is a display rendering
// already, and rendering it again would compress it twice.
// D19's sigmoid by default, Camera Raw's tone by choice (D21).
// D19's sigmoid by default, the DNG reference tone by choice (D21).
if (!non_linear) {
if (mode > 0.5) {
c = camera_raw_tone(c, cr_scale, cr_power, cr_grey);