crw: address the remaining CodeRabbit record findings

- 02 §4: the decoder refuses the G5 with Error::Unsupported; the embedded-JPEG fallback is the
  caller's, not the decoder's.
- 04: the Auto-slot claim holds outside the white-balance preset captures.
- The record README no longer says it holds everything in the order it happened: the derivation
  trail stays at the pinned LightCraft revision.
- docs/clean-room.md allows that split for a derivation done in another repository, so the
  standard and the CRW record agree.
This commit is contained in:
Dylan M. Taylor committed 2026-10-28 22:19:44 -04:00
1 parent b600e6a5cd
commit 8829439d68
4 files changed
+10 -6

No files matched your search

+2 -2
View File
@@ -99,8 +99,8 @@ which the Rust implementation may normalise, provided the verification table of
- **G5 anomaly**: its entropy stream decodes end-to-end with the selector-1 tables,
but values diverge beginning at sample 2056 (= 4 × 514), and its low-bits plane fits
no tested layout (top rows mostly match, decaying to 0 %, no constant shift). The
decoder must detect the G5 (CanonModelID / make-model) and fall back to the embedded
JPEG until a follow-up derivation resolves it.
decoder detects the G5 by its make-model and returns `Error::Unsupported` until a
follow-up derivation resolves it; a caller may fall back to the embedded JPEG.
- The exact meaning of each file's tail bytes (handled by the stream-end rule).
- Big-endian (`MM`) CIFF files: no sample exists.
- PowerShot G2/G3/Pro1/Pro70/S30–S70: no CC0 samples (licence-excluded); decodable
+1 -1
View File
@@ -75,7 +75,7 @@ vs −0.67 GRBG). Unsampled PowerShots default to RGGB, unverified.
(γ-model error), so the slot is chosen by metadata, not by fit.
- **Slot selection**: ShotInfo (0x102a) index 7 is the WhiteBalance setting (ExifTool prose:
0 Auto, 1 Daylight, 2 Cloudy, 3 Tungsten, 4 Fluorescent, 5 Flash, 6 Custom, 8 Shade,
9 Kelvin). Every corpus file reads 0 (Auto) → slot 0.
9 Kelvin). Every corpus file outside the preset captures below reads 0 (Auto) → slot 0.
- **D60 preset mapping verified** (2026-10-14): the maintainer shot one overcast scene at
each setting, Auto, Daylight, Cloudy, Tungsten, Fluorescent, Flash and Custom, ISO 100,
within a minute (all seven decode sample-exact). Slots 1–6 hold the same multipliers in
+3 -3
View File
@@ -1,9 +1,9 @@
# Canon CRW clean-room derivation record
Everything that establishes how `craft-crw` decodes a CRW, in the order it happened. The record was
What `craft-crw` decodes a CRW from, and the evidence that it is right. The full record was
produced in LightCraft (`clean-room/crw/`, branch `clean-room-crw-format-decode`, revision
`6ca439b5155820d2befeacd81ec0c6a80b2bd3bc`; the record is identical at `70c755e4`, where the decoder was ported) between 2026-10-12 and 2026-10-25 and moved here
**verbatim** when the decoder became this shared crate. The documents are the evidence: they are
`6ca439b5155820d2befeacd81ec0c6a80b2bd3bc`; the record is identical at `70c755e4`, where the decoder was ported) between 2026-10-12 and 2026-10-25; the documents below moved here
**verbatim** when the decoder became this shared crate, and the derivation trail stays at that revision. The documents are the evidence: they are
not rewritten after the fact, so paths they mention are LightCraft's paths of that time (the
mapping is below).
+4
View File
@@ -65,6 +65,10 @@ folder with:
8. **Table data** lives in the record as JSON and is rendered into Rust by a committed script; the
generated file says so and is never edited by hand.
When the derivation was done in another repository, the crate's `clean-room/` may hold only items
3, 5, 6 and 8, provided it pins that repository, path and revision (in its README and in `NOTICE`)
for the starting assumptions, the plan and the derivation documents, as `craft-crw` does.
Scripts in the record use the Python standard library only and run under `python -I`. Local-only
material (reference models, oracle binaries, copyrighted specification PDFs, dumps that may carry
personal metadata) is named in the record with how to obtain it, and is gitignored.