mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-26 19:17:02 -06:00
LR-IMP-FORMATS: EOS R6 Mark III as-shot white balance (ColorData version 66)
Version 66 keeps version 64's as-shot white balance and black level offsets; its word 661 is below where the sensor clips, so the white level stays measured from the data. Checked on 33 R6 Mark III files from 12 shoots: all now open with their as-shot white balance, black levels match the masked columns. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017JKdR4oZ3jRSPPwMLLTa2U
This commit is contained in:
Vendored
+18
-5
@@ -135,13 +135,21 @@ struct CameraLevels {
|
||||
|
||||
/// Canon's versioned word arrays. Offsets are word indices from the published tag tables, not
|
||||
/// byte offsets. The four as-shot WB values are R, G, G, B, independent of the CFA layout.
|
||||
///
|
||||
/// Version 66 (EOS R6 Mark III) keeps version 64's as-shot WB and black level offsets, measured on
|
||||
/// 33 files from 12 shoots: the as-shot quadruple is followed by its colour temperature and then
|
||||
/// the fixed preset table (Daylight 5200 K, Shade 7000 K, ...), and the black levels equal the
|
||||
/// masked-column levels in every file. Its word 661 (14351 or 13995) is not the clipping point:
|
||||
/// highlights pile up at 16383 and run smoothly through the range between, so the white level is
|
||||
/// measured from the data instead.
|
||||
fn camera_levels(maker: Option<&Ifd>, bits: u8) -> CameraLevels {
|
||||
let Some(values) = maker.and_then(|m| m.u64s(COLOR_DATA)) else { return CameraLevels::default() };
|
||||
let offsets = match values.first().copied() {
|
||||
Some(16..=19) => (71, 329, 797),
|
||||
Some(32 | 33) => (85, 343, 811),
|
||||
Some(34 | 48) => (105, 363, 641),
|
||||
Some(64 | 65) => (105, 383, 661),
|
||||
Some(16..=19) => (71, 329, Some(797)),
|
||||
Some(32 | 33) => (85, 343, Some(811)),
|
||||
Some(34 | 48) => (105, 363, Some(641)),
|
||||
Some(64 | 65) => (105, 383, Some(661)),
|
||||
Some(66) => (105, 383, None),
|
||||
_ => return CameraLevels::default(),
|
||||
};
|
||||
let full = ((1u32 << u32::from(bits.clamp(1, 16))) - 1) as f32;
|
||||
@@ -160,7 +168,7 @@ fn camera_levels(maker: Option<&Ifd>, bits: u8) -> CameraLevels {
|
||||
});
|
||||
let black = quadruple(offsets.1).filter(|v| v.iter().any(|&b| b > 0.0) && v.iter().all(|&b| b >= 0.0 && b < full * 0.5));
|
||||
let max_black = black.map(|v| v.into_iter().fold(0.0f32, f32::max)).unwrap_or(0.0);
|
||||
let white = values.get(offsets.2).map(|&v| v as f32).filter(|&v| v > max_black && v >= full * 0.5 && v <= full);
|
||||
let white = offsets.2.and_then(|at| values.get(at)).map(|&v| v as f32).filter(|&v| v > max_black && v >= full * 0.5 && v <= full);
|
||||
CameraLevels { wb, black, white }
|
||||
}
|
||||
|
||||
@@ -526,6 +534,11 @@ mod tests {
|
||||
assert_eq!(levels.black, Some([100.0, 101.0, 102.0, 103.0]));
|
||||
assert_eq!(levels.white, Some(15000.0));
|
||||
}
|
||||
// Version 66 (EOS R6 Mark III): as-shot WB and black from the table, white from the data.
|
||||
let levels = camera_levels(Some(&maker(66, 105, 383, 661)), 14);
|
||||
assert_eq!(levels.wb, Some([2.0, 1.0, 1.5]));
|
||||
assert_eq!(levels.black, Some([100.0, 101.0, 102.0, 103.0]));
|
||||
assert_eq!(levels.white, None);
|
||||
assert!(camera_levels(Some(&maker(255, 71, 329, 797)), 14).wb.is_none());
|
||||
assert!(camera_levels(None, 14).black.is_none());
|
||||
}
|
||||
|
||||
@@ -5,6 +5,14 @@ The CR3 adapter reads the CRX Bayer track, `CMP1` compression descriptor,
|
||||
black/white levels and the default crop come from the file. A Dual Pixel delta
|
||||
track is never substituted for the primary Bayer track.
|
||||
|
||||
The EOS R6 Mark III writes `ColorData` version 66, which keeps version 64's as-shot white balance (word 105) and
|
||||
black level (word 383) offsets. Measured on 33 files from 12 shoots (ISO 100–12800, 1/1250 s–25 s): the as-shot
|
||||
R, G, G, B quadruple is followed by its colour temperature (3271–7424 K across the shoots) and then the fixed
|
||||
preset table (Daylight 5200 K, Shade 7000 K, Cloudy 6000 K, Tungsten 3200 K, ...), and the black levels equal the
|
||||
masked-column levels in every file (512 at low ISO, 2047–2048 above). Word 661 holds 14351 or 13995, but it is not
|
||||
the clipping point: highlights pile up at 16383 and run smoothly through the range above 14351, so version 66
|
||||
takes its white level from the data.
|
||||
|
||||
The in-camera aspect ratio (3:2, 4:3, 16:9, 1:1) is not applied to the sensor data. The maker note's
|
||||
`AspectInfo` (tag `0x009a`: aspect code, cropped width, height, left, top) gives the shot's rectangle inside the
|
||||
recommended crop, and the decoder uses it as the default crop, so the developed image has the shape the photographer
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user