Skip to main content

Module raw_preview

Module raw_preview 

Source
Expand description

Extract the largest embedded JPEG preview from a TIFF-based RAW.

TIFF-based RAW formats (NEF, CR2, CR3, ARW, DNG, ORF, RW2, PEF, RWL, SRW, …) all pack one or more full-decoded JPEGs at known offsets inside the file. Cameras embed these for the rear-screen preview — they’re exactly what every consumer photo-viewer shows when it claims to “open a RAW”. The image is the manufacturer’s intended rendering: correct white balance, correct colours, correct sharpening. Better than anything an open-source debayer pipeline produces without the camera’s proprietary DCP profiles.

§Why a hand-rolled walker

rawloader and rawler give you Bayer sensor data, not embedded JPEGs. libraw would work but is a native C dep we don’t want to ship per-platform. kamadak-exif (already a dep) walks IFD0, IFD1, plus the EXIF / GPS / Interop SubIFDs — but the preview JPEGs in NEF / CR2 / ARW / DNG / ORF live in a TIFF “SubIFD” chain referenced by tag 0x014A, which kamadak doesn’t traverse.

So we walk the TIFF directly. ~150 lines of well-defined byte pushing. No deps. Covers every TIFF-based RAW in one shot.

§Algorithm

  1. Read the 8-byte TIFF header. Confirm II*\0 (little-endian) or MM\0* (big-endian). Note the offset of IFD0.
  2. Recursively walk every IFD reachable from IFD0:
    • IFD chain via the NextIFD offset (last 4 bytes of each IFD)
    • SubIFD chain via tag 0x014A
    • EXIF / GPS / Interop SubIFDs via tags 0x8769 / 0x8825 / 0xA005 Each visit short-circuits if we’ve already seen that offset, so a malformed file with a cycle can’t hang us.
  3. For each IFD, look for two embedded-JPEG idioms: a. JPEGInterchangeFormat (0x0201) + length (0x0202) b. StripOffsets (0x0111) + byte counts (0x0117) where Compression (0x0103) is 6 (old-style JPEG) or 7 (new).
  4. Sanity-bound each candidate against the file size, then return the bytes of the largest one (or None if no candidate found).

§What this doesn’t do

  • RAF (Fujifilm) — custom container, not TIFF. Falls through to the image::open path which fails; the user gets a clear error. ~100 LOC of standalone parser would add it; do that when a Fuji user actually asks.
  • Full Bayer demosaic — out of scope; that’s a separate path that would need DCP colour profiles and per-camera tuning.

Functions§

extract_largest_preview
Bytes of the largest embedded JPEG in this TIFF-based RAW, or None if the file doesn’t contain a recognisable embedded preview.