EXR Metadata Contract ===================== Goal ---- Define a stable representation for OpenEXR header metadata in ``MetaStore`` so read/export workflows are deterministic and lossless. Contract constant: ``kExrCanonicalEncodingVersion == 1``. Key Space --------- Each EXR attribute is keyed as ``MetaKeyKind::ExrAttribute`` with: - ``part_index`` - attribute ``name`` Wire Contract ------------- For EXR entries: - ``Origin::wire_type.family = WireFamily::Other`` - ``Origin::wire_type.code = EXR type code`` - ``Origin::wire_count = raw attribute byte size`` Unknown/custom EXR attribute types are preserved as: - ``MetaValueKind::Bytes`` raw payload - optional ``Origin::wire_type_name`` with original EXR type string Canonical Value Mapping ----------------------- - ``int`` -> scalar ``I32`` - ``float`` -> scalar ``F32`` - ``double`` -> scalar ``F64`` - ``rational`` -> scalar ``SRational`` - ``string`` -> text (ASCII/UTF-8/Unknown best-effort) - ``v2*``/``v3*`` -> numeric arrays - ``m33*``/``m44*`` -> numeric arrays (row-major) - ``box2*`` -> arrays ``[min.x, min.y, max.x, max.y]`` - ``compression``/``lineOrder``/``envmap``/``deepImageState`` -> scalar ``U8`` - ``timecode`` -> ``U32[2]`` - ``keycode`` -> ``I32[7]`` - ``tiledesc`` -> ``U32[3]`` (x size, y size, mode) - complex payloads (for example ``chlist``, ``preview``, ``stringvector``) remain bytes in core storage Reference --------- - Decoder API: ``openmeta/exr_decode.h`` - EXR tests: ``tests/exr_decode_test.cc`` - Interop naming: ``interop_api.rst``