Carry Lightroom's tone sliders across at measured strengths

Contrast2012 and the four recovery sliders were imported one to one. They do
not mean the same thing here: fitted on the library's Lightroom 6 exports and
their raws — each photograph's sliders carried across as slider × factor, one
factor per slider, on about 90 exports with no look applied, on the Camera Raw
default rendering — ours needed contrast at about a tenth (Lightroom's −100
imported as ours flattens a frame to grey), highlights ×1.4, shadows ×1.9 and
blacks ×1.25. Whites fitted below 1 every time without agreeing where; 0.5 is
a hedge, and says so. Vibrance stays one to one: the op itself is now
calibrated to Lightroom's.
This commit is contained in:
2026-10-03 23:04:46 -04:00
parent c343ac79d3
commit a36ec98b36
2 changed files with 29 additions and 15 deletions
+28 -14
View File
@@ -83,35 +83,43 @@ const MAPPINGS: &[Mapping] = &[
param: "exposure",
convert: Convert::Direct,
},
// The five tone sliders do not mean the same thing in the two applications,
// whatever their shared ±100 suggests. The factors were fitted against the
// library's own Lightroom 6 exports and their raws (darkroom-lrfit, 2026-10):
// each photograph's sliders carried across as `slider × factor`, one factor
// per slider, on ~90 exports with no look applied. Contrast is ours at a
// tenth — at −100 ours flattens a frame to grey — and our shadows need
// nearly twice Lightroom's number. Whites barely appears in those exports;
// every fit put it under 1 but none agreed where, so 0.5 is a hedge.
Mapping {
crs: "Contrast2012",
op: "contrast",
param: "contrast",
convert: Convert::Direct,
convert: Convert::Scale(0.1),
},
Mapping {
crs: "Highlights2012",
op: "highlights_shadows",
param: "highlights",
convert: Convert::Direct,
convert: Convert::Scale(1.4),
},
Mapping {
crs: "Shadows2012",
op: "highlights_shadows",
param: "shadows",
convert: Convert::Direct,
convert: Convert::Scale(1.9),
},
Mapping {
crs: "Whites2012",
op: "blacks_whites",
param: "whites",
convert: Convert::Direct,
convert: Convert::Scale(0.5),
},
Mapping {
crs: "Blacks2012",
op: "blacks_whites",
param: "blacks",
convert: Convert::Direct,
convert: Convert::Scale(1.25),
},
Mapping {
crs: "Clarity2012",
@@ -566,8 +574,8 @@ mod tests {
assert_eq!(get("colour_mixer", "violet_sat"), Some(23.0));
assert_eq!(get("colour_mixer", "red_hue"), Some(-5.0));
assert_eq!(get("colour_mixer", "green_lum"), Some(7.0));
assert_eq!(get("highlights_shadows", "highlights"), Some(-40.0));
assert_eq!(get("blacks_whites", "blacks"), Some(-20.0));
assert_eq!(get("highlights_shadows", "highlights"), Some(-40.0 * 1.4));
assert_eq!(get("blacks_whites", "blacks"), Some(-20.0 * 1.25));
}
#[test]
@@ -588,7 +596,7 @@ mod tests {
let get = |op: &str, param: &str| p.get(&(op.to_string(), param.to_string())).copied();
assert_eq!(get("colour_mixer", "blue_sat"), Some(58.0));
assert_eq!(get("colour_mixer", "cyan_sat"), Some(50.0));
assert_eq!(get("highlights_shadows", "highlights"), Some(-40.0));
assert_eq!(get("highlights_shadows", "highlights"), Some(-40.0 * 1.4));
}
#[test]
@@ -642,14 +650,20 @@ mod tests {
fn the_settings_that_share_a_convention_come_across_unchanged() {
let import = read_xmp(ATTRIBUTE_FORM).unwrap();
assert_eq!(value(&import, "exposure", "exposure"), Some(0.75));
assert_eq!(value(&import, "contrast", "contrast"), Some(25.0));
assert_eq!(value(&import, "contrast", "contrast"), Some(25.0 * 0.1));
assert_eq!(
value(&import, "highlights_shadows", "highlights"),
Some(-40.0)
Some(-40.0 * 1.4)
);
assert_eq!(
value(&import, "highlights_shadows", "shadows"),
Some(30.0 * 1.9)
);
assert_eq!(value(&import, "blacks_whites", "whites"), Some(10.0 * 0.5));
assert_eq!(
value(&import, "blacks_whites", "blacks"),
Some(-15.0 * 1.25)
);
assert_eq!(value(&import, "highlights_shadows", "shadows"), Some(30.0));
assert_eq!(value(&import, "blacks_whites", "whites"), Some(10.0));
assert_eq!(value(&import, "blacks_whites", "blacks"), Some(-15.0));
assert_eq!(value(&import, "clarity", "amount"), Some(12.0));
assert_eq!(value(&import, "texture", "amount"), Some(8.0));
assert_eq!(value(&import, "vibrance", "vibrance"), Some(20.0));
@@ -690,7 +704,7 @@ mod tests {
// does not say which shape it used.
let import = read_xmp(ELEMENT_FORM).unwrap();
assert_eq!(value(&import, "exposure", "exposure"), Some(0.75));
assert_eq!(value(&import, "contrast", "contrast"), Some(25.0));
assert_eq!(value(&import, "contrast", "contrast"), Some(25.0 * 0.1));
}
#[test]
File diff suppressed because one or more lines are too long