mirror of
https://github.com/storytold/lightcraft.git
synced 2026-10-24 10:09:01 -06:00
A grid thumbnail and a loupe preview of an unedited raw show the camera's embedded JPEG, which sits near the start of the file — for a 24 MP Fuji RAF, 5.6 MB of a 56 MB file (measured: DSCF9492.RAF). The loader read the file whole and threw the sensor data away, so every preview paid for 50 MB nobody looked at. On a local disk that is merely wasteful; on a network share, where photographers keep libraries, it is the wait: the same preview took 10 s over a GVFS/SMB Wi-Fi share against 0.96 s after this change. - `lightcraft_raw::bounded_preview(bytes)` locates the preview from the header alone and reports its byte range; `embedded_preview_from_range` extracts it, byte for byte what `embedded_preview` returns for the whole file (the pointer is read from the RAF header's fixed u32s at 84/88). - `engine::files::preview_window` reads a 4 KiB prefix, then — because the container reader clamps a slice to the buffer it was given, so a short prefix reports a plausible but truncated 3948 bytes — re-reads exactly the extent the header declares, and takes the window out of the prefix rather than reading those bytes twice. `LIGHTCRAFT_PROFILE=1` prints what each preview cost. - Formats whose preview only the whole file reveals (CR3 boxes, TIFF pointer tags past the prefix, CRW/MRW/X3F scans), a lying pointer, a short read and a file that changes underneath us all fall back to the whole-file path: a damaged header never costs the user their preview. - Tests: the header range matches `embedded_preview` byte for byte, with a clamped prefix, a padded extent, a late pointer, a lying pointer and a non-JPEG window covered; on a synthetic RAF with a 200 KB tail the quick path and the whole-file path produce identical pixels and the read stays under half the file; `crates/engine/tests/preview_read.rs` (opt-in, `#[ignore]`) measures a real file on a share. No raw fixture is committed. - `docs/raw-preview-reads.md` records the mechanism and the numbers. Co-Authored-By: DeepSeek V3.2 <noreply@deepseek.com>