Skip to content

feat: Sony A7R VI (ILCE-7RM6) support + general ARW6 canvas geometry - #2

Draft
puzza007 wants to merge 5 commits into
feat/sony-a7v-support-0.22.2from
feat/sony-a7rm6-support-0.22.2
Draft

feat: Sony A7R VI (ILCE-7RM6) support + general ARW6 canvas geometry#2
puzza007 wants to merge 5 commits into
feat/sony-a7v-support-0.22.2from
feat/sony-a7rm6-support-0.22.2

Conversation

@puzza007

Copy link
Copy Markdown
Member

Adds the Sony A7R VI (ILCE-7RM6) on top of the A7 V branch, and replaces the ARW6 decoder's special-cased vertical layout handling with the derived canvas geometry. Stacked on feat/sony-a7v-support-0.22.2.

Camera support (edbe9d65-lineage commit)

  • Camera ID 0x19a (SonyModelID 410), body features + Tag9050d group, normalized model, camera list entry
  • Crop table: FF 10240/10016 → 9984×6656, APS-C 6656/6592 → 6528×4352 (from Adobe DNG Converter DefaultCropSize across the full rawdb.dnglab.org CC0 sample matrix)
  • D65 color matrix extracted from Adobe DNG Converter ColorMatrix2 on those samples; independently matches dnglab PR Add support for Sony A7R VI (ILCE-7RM6) dnglab/dnglab#796

Decoder fix: derive the ARW6 vertical canvas geometry

ARW6 lays each tile's component rows on a shared vertical canvas whose origin (comp_top) varies with tile height mod 16, and that origin drives every sub-band's per-chunk row windows and the per-level IDWT merge parity. The decoder previously hard-coded the comp_top = 8 (16-aligned) layout plus a guarded path that is wrong for comp_top = 7 — which is exactly the A7R VI's APS-C frames (height 4372), and also 7R V lossy-medium files upstream. All four APS-C lossy/HQ variants decoded with globally wrong detail (LibRaw#828's failure class).

The fix computes per-lattice spans, extracts rows via the sequential HL/LH/HH slot-fill rule (partial chunks rotate rows across the linear planes; partial-window HH rows are stored at half amplitude), and merges with a parity-aware vertical 5/3 lift. Net −159 lines; the coefficient arithmetic is untouched. Canvas model cross-checked against the format description in abbradar/arw6_decode.

Validation

Bit-exact against Adobe DNG Converter raw output over the full Adobe active area:

  • 12/12 ILCE-7RM6 rawdb samples (FF + APS-C × lossless/lossy/lossy-HQ × landscape/portrait) — including the 4 APS-C lossy/HQ files that fail on upstream master
  • 4/4 ILCE-7M5 pixls.us samples — previously-exact files unchanged, so the general path reproduces the aligned layout bit-for-bit

Worth offering upstream: this closes LibRaw#828's remaining failures and silently-wrong 7R V lossy-medium/small decodes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01S1mAhAaVQjGgRPsXSVVnxp

puzza007 and others added 3 commits July 27, 2026 12:37
Camera ID 0x19a (SonyModelID 410), FF 10240/10016 and APS-C 6656/6592
raw-width variants cropping to 9984x6656 / 6528x4352 per Adobe DNG
Converter DefaultCropSize. D65 color matrix extracted from Adobe DNG
Converter ColorMatrix2 on rawdb.dnglab.org CC0 samples (matches dnglab
PR LibRaw#796). Lossless frames decode via the existing LJpeg path; lossy/HQ
"Compressed RAW 2" frames use the ARW6 decoder already on this branch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1mAhAaVQjGgRPsXSVVnxp
…sing

ARW6 lays each tile's component rows on a shared vertical canvas whose
origin (comp_top) varies with the tile height modulo 16 and drives every
sub-band's per-chunk row windows and the per-level IDWT merge parity. The
decoder hard-coded one aligned layout (comp_top 8) plus a guarded path
that was only right for some non-aligned heights; ILCE-7RM6 APS-C frames
(4372 rows, comp_top 7) decoded with globally wrong detail.

Replace the per-case synthesis functions with computed lattice spans, a
general slot extractor (chunk rows fill fixed record slots sequentially
in HL/LH/HH order, so partial chunks shift rows across the linear
planes; partial-window HH rows are stored at half amplitude), and a
parity-aware vertical 5/3 lift.

Validated bit-identical against Adobe DNG Converter raw output on all 12
ILCE-7RM6 rawdb samples (FF + APS-C x lossless/lossy/HQ x both orientations)
and all 4 ILCE-7M5 pixls.us ARW6/LJpeg samples (no change to previously
exact files). Canvas model cross-checked against the format description
in abbradar/arw6_decode (LibRaw#828).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1mAhAaVQjGgRPsXSVVnxp
Post-rewrite cleanup, no decoded-byte changes (re-validated bit-exact
against Adobe DNG Converter on all 16 A7R VI + A7 V sample pairs):

- size packet planes to the validated block count and drop the vestigial
  padded-height row formula (sony_arw6_expected_packet_rows) and
  sony_arw6_align_up
- pass the tile's chunk count into decode_packet_arrays instead of
  re-deriving geometry per packet; take comp_height straight from the
  stream header
- drop integrate_type1's constant rows/dc_offset parameters and the
  extractor's row-multiplier parameter (always the span's rpc)
- move the four result planes instead of deep-copying (~340 MB per
  full-frame tile)
- const ints for the canvas constants, std::max/min window clamps

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1mAhAaVQjGgRPsXSVVnxp
narrative-donc and others added 2 commits August 24, 2026 11:13
The ILCE-7M5 is routed to the Tag9050d layout, which reads InternalBodySerial
from six bytes at offset 0x38 of the 0x9050 block. Those bytes are not a body
serial on this camera: the value changes from frame to frame, so anything
keying on camera identity sees every frame as a different body. It split a
2-second burst into twelve separate groups in a scene-clustering consumer.

Measured across two bodies and both shipped firmwares:

  - v1.01, one 12-frame burst: twelve distinct values (191100288e43,
    180010000028, 44100000002, ...). Zero of the 256 raw bytes of the block
    are constant across the burst, so no offset in it holds a body serial for
    these files. The block does not carry the layout's five-zero-byte prefix
    and nothing else in it decodes either - SonyFNumber reads as 57511365
    against a real f/2.8, ShutterCount ranges 320..8683552 within the burst.

  - v1.00, one session: three distinct values (2cff0000b108, e1fe0000e908,
    37ff0000b908). Here the block does carry the prefix and its other fields
    decode correctly, but the six bytes at 0x38 still move between frames -
    they read XX ff 00 00 YY 08, a counter rather than an identity.

So the field is wrong on v1.01 because the whole block is a different format,
and wrong on v1.00 because 0x38 was never the serial. Exclude the camera from
this read, in the same way the 9050a branch already excludes the NEX-5N, NEX-7
and NEX-VG20.

Bodies that do have an identity report it in EXIF BodySerialNumber, which is
read elsewhere: the v1.00 samples keep BodySerial 02052278 with this change.
Scoped to the serial read alone, so CurAp, LensMount, LensType2 and
ImageCount3 continue to decode from the block on firmwares where it is valid.

Verified: InternalBodySerial is now empty on all 23 A7 V files across both
bodies, BodySerial 02052278 is preserved on the six samples that carry it,
and lens/aperture/ISO still decode on v1.00. Canon 5D Mark IV, 250D, 7D,
Nikon D5100, Fuji X20 and DSLR-A390 fixtures are unchanged.

The ILCE-7RM6 shares the Tag9050d routing and may well have the same problem,
but is not excluded here - no sample was available to test it.
fix(sony): don't emit a bogus InternalBodySerial for the A7 V
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants