EXR: Cryptomatte layers list, decode and hash to the specification (#2180)

* EXR: Cryptomatte layers list, decode and hash to the specification

Cryptomatte (specification 1.2) carries per-pixel object and material
IDs with coverage in <layer>NN.red/.green channel pairs, announced by
cryptomatte/<key>/name|hash|conversion|manifest header attributes - the
ID channels Arnold, V-Ray, Redshift, Mantra/Karma and Cycles write next
to the beauty pass.

cryptomatte_layers lists every layer from the headers alone (name, key,
channels, the embedded manifest parsed and capped at 16 MiB, a sidecar
pointer); decode_cryptomatte returns the per-pixel (ID, coverage) pairs
above zero, sorted by descending coverage; cryptomatte_id hashes names
the reference way (MurmurHash3 x86-32, the exponent fixed away from
denormals/inf/NaN, read as f32 bits) - verified against the official
test vectors - and cryptomatte_key/cryptomatte_preview_color expose the
metadata key and preview colour. Files with deep parts are refused, like
the other flat part decoders.

* chore(ui): format prefs_ui (the workspace fmt gate is red on main until #2417 lands)

* codecs: Cryptomatte decode checks the layer size without truncating casts

Count each pixel's pair list in the allocation check too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Elvis33LE
2026-10-10 06:40:49 -04:00
committed by GitHub
co-authored by Claude Opus 5.5 Brandon Thomas
parent a737281fad
commit 291f30da55
9 changed files with 549 additions and 5 deletions
+6
View File
@@ -160,6 +160,12 @@ the same.
* Reads at full resolution, from the data window.
* Channel names are matched by suffix, so `layer.R` counts as `R`.
* Subsampled channels are unsupported.
* Cryptomatte layers (specification 1.2, as written by Arnold, V-Ray, Redshift, Mantra/Karma
and Cycles) are listed and decoded structurally: `cryptomatte_layers` reads the header
attributes, channels and embedded manifest without pixels, `decode_cryptomatte` returns the
per-pixel (ID, coverage) pairs, and `cryptomatte_id`/`cryptomatte_key`/`cryptomatte_preview_color`
hash names to IDs the way the reference implementation does (official test vectors in the
test suite).
* Deep data (scanlines or single-level tiles, compressed NONE, RLE or ZIPS) opens as a flat
image: each pixel's samples are composited into one, with
`DecodeWarning::DeepFlattened` because per-pixel depth is not kept. Deep ZIP (16-line