From 5bf455c456344883849f976347e5cc57fafe085e Mon Sep 17 00:00:00 2001 From: dev-null-undefined Date: Tue, 13 Oct 2026 11:45:33 +0200 Subject: [PATCH] LRC-LIB-CATALOG-IMPORT: an ARW6 is described from the whole file, not a partial read header_plan skipped an ARW6's strip but its first 64 KB and then said Ready, while the ARW6 header probe (Mode::Header) validates every tile: its picture header, stream tables and the first lines of its residual stream, which lie in the skipped bytes. The probe of the partly read buffer then failed ("ARW6 first-half row count outside 2..=7") where the whole file succeeds: sparse_corpus failed on arw6-sony-ilce7rm6-apsc-land-c.arw, the first ARW6 file it reads (it stops at the first failure). Like NEF, ORF and PEF, whose header probes read samples, an ARW6 now gets HeaderPlan::Whole from the header plan. The preview plan is unchanged: the embedded preview reads no tile, and the 13 ARW previews in the corpus are still read from 21 % of their bytes. Only the test reads the header plan today (the app's partial reads use preview_plan), so no import changes. New test: a synthetic two-tile ARW6 whose second tile lies past a first one of bulk size (Ready before, Whole now). sparse_corpus passes on the 8 ILCE-7RM6 ARW6 files. cargo test --workspace: 3205 passed, 1 failed, visualize::tests:: all_masks_overlay_shows_every_visible_mask_at_once, which fails on main b3d392b4 too (PR #1456 addresses it); fmt, clippy, parity, layers, assets and wasm pass. Sources: own design. Co-Authored-By: Claude Opus 5.5 --- crates/raw/src/sparse.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/crates/raw/src/sparse.rs b/crates/raw/src/sparse.rs index 14fa3c1f8..e5a8e787d 100644 --- a/crates/raw/src/sparse.rs +++ b/crates/raw/src/sparse.rs @@ -13,9 +13,9 @@ //! tracks (keeping the raw track's coding headers and quantization maps, and the timed-metadata //! track where Canon puts the as-shot white balance), a RAF's CFA strip (keeping its compression //! header) and a Panasonic RW2's raw data. Formats whose header probe reads samples (NEF: masked -//! columns; ORF: bit depth and CFA phase; PEF: dark borders) and anything else get -//! [`HeaderPlan::Whole`], as does a structure that is incomplete, inconsistent or keeps metadata -//! inside its sample data: the plan never guesses. +//! columns; ORF: bit depth and CFA phase; PEF: dark borders; ARW6, for its header plan only: the +//! start of every tile) and anything else get [`HeaderPlan::Whole`], as does a structure that is +//! incomplete, inconsistent or keeps metadata inside its sample data: the plan never guesses. use std::collections::HashSet; @@ -236,6 +236,8 @@ fn tiff_plan(bytes: &[u8], loaded: &Ranges, preview: bool) -> HeaderPlan { let chunks: Vec<(u64, u64)> = match ifd.image() { // a preview's strips are read when the preview is wanted: only the raw image is skipped Ok(info) if preview && !matches!(info.photometric, t::photometric::CFA | t::photometric::LINEAR_RAW) => continue, + // (Sony Compressed RAW 2: the header probe decodes the start of every tile; a preview reads none) + Ok(info) if !preview && info.compression == 32766 => return HeaderPlan::Whole("an ARW6 header probe reads its tiles"), Ok(info) => info.chunks(len).iter().map(|c| (c.offset, c.len)).collect(), // a raw IFD without the tags a TIFF image needs (an older CR2's) still lists its strips Err(_) => match (ifd.u64s(t::STRIP_OFFSETS), ifd.u64s(t::STRIP_BYTE_COUNTS)) { @@ -550,4 +552,17 @@ mod tests { raf[104..108].copy_from_slice(&1000u32.to_be_bytes()); assert_eq!(run(&raf, 160, 0).0, HeaderPlan::Whole("RAF raw container")); } + + /// An ARW6 header probe reads every tile's headers and the first lines of its data, which lie in the strip a + /// plan would skip: here the second tile, past a first one of bulk size. + #[test] + fn arw6_is_described_from_the_whole_file() { + use crate::vendor::arw6_testenc::{Qis, arw6_file, one_tile_quantised}; + let (tile, _) = one_tile_quantised(64, 48, 0, Qis::REAL); + let mut first = tile.clone(); + first.resize(BULK as usize, 0); + let file = arw6_file(&[(0, 0, 64, 48, first), (64, 0, 64, 48, tile)], 128, 48); + assert!(crate::probe_info(&file).is_ok()); + assert_eq!(run(&file, 16, 0).0, HeaderPlan::Whole("an ARW6 header probe reads its tiles")); + } }