//! Print what `decode` extracts from a RAW file. //! //! A sanity check on the pipeline's inputs: black and white levels, the CFA //! pattern after re-phasing, as-shot white balance, and the camera→sRGB //! matrix. Wrong values here produce a wrong image no shader can fix, so it //! is worth being able to see them directly. //! //! ```sh //! cargo run -p dr-decode --example rawinfo -- IMG.CR2 //! ``` fn main() { let Some(path) = std::env::args().nth(1) else { eprintln!("usage: rawinfo "); std::process::exit(2); }; let bytes = std::fs::read(&path).expect("read file"); let raw = dr_decode::decode(&bytes).expect("decode"); println!("file {path}"); println!("readout {} × {}", raw.width, raw.height); println!( "crop {} × {} at ({}, {})", raw.crop.width, raw.crop.height, raw.crop.x, raw.crop.y ); let (dx, dy) = raw.crop.shifts_cfa_phase(); println!( "cfa {:?} (rephased: {dx}, {dy})", raw.cfa_pattern ); println!("black {:?}", raw.black_level); println!("white {}", raw.white_level); println!("wb_coeffs {:?}", raw.wb_coeffs); match raw.color_matrix { Some(m) => { println!("cam→srgb"); for row in m.chunks(3) { println!( " [{:>8.4} {:>8.4} {:>8.4}]", row[0], row[1], row[2] ); } // Each row should sum to roughly 1: a neutral camera-space colour // must stay neutral in sRGB. Far from 1 means the normalisation // or the matrix composition is wrong. let sums: Vec = m.chunks(3).map(|r| r.iter().sum()).collect(); println!("row sums {sums:.4?} (≈1.0 each if correct)"); } None => println!("cam→srgb none — uncalibrated body"), } // Sample the actual data range, which reveals a black-level or bit-depth // mistake faster than any amount of staring at metadata. let (min, max) = raw .data .iter() .fold((u16::MAX, 0u16), |(lo, hi), &v| (lo.min(v), hi.max(v))); println!("sample range {min} … {max}"); }