Build and test / Desktop (Linux) (push) Failing after 54s
Build and test / Layer separation (push) Successful in 22s
Traceability / Requirement traces (push) Failing after 59s
🐳 Android image / Build and push (push) Successful in 12m59s
Build and test / android-image (push) Successful in 13m1s
Build and test / Android (aarch64) (push) Failing after 9m42s
First step of dead pixel removal, and the one that decides whether the rest is worth building: where the map comes from. `rawler` is no help. It knows `OpcodeList1/2/3` exist — it copies them through when *writing* a DNG — but it never decodes them, and the `dng_tags` map it exposes is only ever filled by callers, never by a decoder. So the bytes are read from the IFD directly, which this module was already walking for previews, including the SubIFDs where a DNG keeps its raw IFD. `OpcodeList1` specifically: lists 2 and 3 run after demosaic and after the colour transform, so neither can carry a correction that has to happen on the mosaic. Two opcodes describe defects — `FixBadPixelsList`, which is explicit coordinates plus whole dead rows and columns, and `FixBadPixelsConstant`, which names a sentinel value rather than any coordinates and is left unimplemented until there is a stage to consume it. A half-implementation that guessed at coordinates would be worse than the absence, because it would look like it worked. Two things the tests pin down because both are silent when wrong: a point is stored (row, column) and reading it the other way round lands the correction on the wrong photosite — invisibly, on a square crop — and opcode payloads are big-endian whatever the container's byte order is, so a little-endian TIFF still writes these the other way round. An unknown opcode is stepped over using its declared length rather than abandoning the list, because a camera that corrected its lens as well as its sensor writes both, and losing the map whenever a warp is present would be losing it on most files that have one. Includes `--example defects`, because whether any of this fires is a question about a particular library rather than about the specification.
53 lines
1.7 KiB
Rust
53 lines
1.7 KiB
Rust
//! Report the defect map a raw file carries, if it carries one.
|
|
//!
|
|
//! ```text
|
|
//! cargo run -p dr-decode --example defects -- IMG_6320.dng photo.cr2
|
|
//! ```
|
|
//!
|
|
//! Exists because whether this is worth building a correction stage for is a
|
|
//! question about *your files*, not about the specification: DNGs written by
|
|
//! cameras that map their own sensors carry `OpcodeList1`, conversions from a
|
|
//! proprietary raw usually do not, and no CR2 or scanner TIFF ever does.
|
|
//! Rather than guess, point this at the library and see.
|
|
|
|
fn main() {
|
|
let files: Vec<String> = std::env::args().skip(1).collect();
|
|
if files.is_empty() {
|
|
eprintln!("usage: defects <raw file>...");
|
|
std::process::exit(2);
|
|
}
|
|
|
|
for path in &files {
|
|
let bytes = match std::fs::read(path) {
|
|
Ok(b) => b,
|
|
Err(e) => {
|
|
println!("{path}: unreadable — {e}");
|
|
continue;
|
|
}
|
|
};
|
|
|
|
let found = dr_decode::defects(&bytes);
|
|
if found.is_empty() {
|
|
println!("{path}: no defect map");
|
|
continue;
|
|
}
|
|
|
|
println!(
|
|
"{path}: {} bad pixel(s), {} bad line(s)",
|
|
found.pixels.len(),
|
|
found.lines.len()
|
|
);
|
|
// A handful, so the output stays readable on a sensor reporting
|
|
// hundreds — the count above is the number that matters.
|
|
for p in found.pixels.iter().take(8) {
|
|
println!(" pixel at {},{}", p.x, p.y);
|
|
}
|
|
for l in found.lines.iter().take(8) {
|
|
match l {
|
|
dr_decode::BadLine::Column(x) => println!(" dead column {x}"),
|
|
dr_decode::BadLine::Row(y) => println!(" dead row {y}"),
|
|
}
|
|
}
|
|
}
|
|
}
|