mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
Issue #212: Raw: keep vendor white balance when writing DNG
NEF (and other vendor raws without a colour matrix) carry their as-shot white balance as vendor multipliers, not as a DNG AsShotNeutral. The DNG writer only copied AsShotNeutral/AsShotWhiteXY, so Convert to DNG and Copy as DNG produced files with no white balance at all, which develop dark and green. Write the reciprocal of the vendor multipliers as AsShotNeutral when the source has no DNG white of its own.
This commit is contained in:
@@ -177,6 +177,9 @@ pub fn write_dng(raw: &RawImage, opts: &DngWriteOptions) -> Result<Vec<u8>> {
|
||||
ifd.set(t::AS_SHOT_NEUTRAL, rat_vec(&v));
|
||||
} else if let Some(xy) = c.as_shot_white_xy {
|
||||
ifd.set(t::AS_SHOT_WHITE_XY, rat_vec(&[xy.x, xy.y]));
|
||||
} else if let Some(m) = raw.wb_multipliers.filter(|m| m.iter().all(|v| *v > 0.0 && v.is_finite())) {
|
||||
// vendor raws (NEF, ARW…) carry white balance as multipliers: the DNG neutral is their reciprocal
|
||||
ifd.set(t::AS_SHOT_NEUTRAL, rat_vec(&m.map(|v| 1.0 / v as f64)));
|
||||
}
|
||||
ifd.set(t::BASELINE_EXPOSURE, Value::SRational(vec![srational(c.baseline_exposure)]));
|
||||
// the source's own profile look travels with its data (conversions, smart previews, merges)
|
||||
|
||||
@@ -453,6 +453,22 @@ fn colour_transform_from_decoded_dng() {
|
||||
assert!(o.iter().all(|v| (v - 1.0).abs() < 1e-9));
|
||||
}
|
||||
|
||||
/// Issue #212: a NEF converted to DNG came out dark and green. NEF white balance is vendor multipliers
|
||||
/// (no colour matrix, no `AsShotNeutral`); the DNG must carry them as its as-shot neutral.
|
||||
#[test]
|
||||
fn vendor_white_balance_survives_dng_conversion() {
|
||||
let mut raw = synthetic(16, 16, Some(Cfa::bayer("RGGB").unwrap()), 1);
|
||||
raw.color = ColorData::default();
|
||||
raw.wb_multipliers = Some([2.25, 1.0, 1.7421875]);
|
||||
let before = lightcraft_raw::color::camera_transform(&raw, lightcraft_raw::color::as_shot_white_xy(&raw));
|
||||
let back = decode(&write_dng(&raw, &DngWriteOptions::default()).unwrap()).unwrap();
|
||||
let after = lightcraft_raw::color::camera_transform(&back, lightcraft_raw::color::as_shot_white_xy(&back));
|
||||
for c in 0..3 {
|
||||
assert!((before.wb[c] - after.wb[c]).abs() < 1e-3, "{:?} vs {:?}", before.wb, after.wb);
|
||||
}
|
||||
assert!((after.wb[0] - 2.25).abs() < 1e-3 && (after.wb[2] - 1.7421875).abs() < 1e-3, "{:?}", after.wb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_unsupported_and_broken() {
|
||||
let (w, h) = (8, 8);
|
||||
|
||||
Reference in New Issue
Block a user