pub fn check_gain_map_roundtrip<E, D>(enc: E, dec: D) -> ConformanceExpand description
The gain-map encode/decode contract (docs/gainmap-pipeline-scope-2026-06-08.md
Phases 1, 2 and 4, tracked in zencodec#24), for every declared/undeclared
combination of EncodeCapabilities::gain_map
and DecodeCapabilities::gain_map:
Encoder undeclared ⇒ with_gain_map_pixels and with_gain_map_encoded
must fail with UnsupportedOperation::GainMapEncode (the trait default) —
a dropped gain map is lost HDR, so silence is the one forbidden outcome.
Encoder declared ⇒ for each case of the test matrix (1-channel forward, 3-channel forward, 1-channel backward-direction — sub-resolution 10×7 maps on a 20×14 RGB8 base, ISO 21496-1 params with only dyadic values, PQ alternate CICP):
with_gain_map_pixelsaccepts the map and the base still encodes;with_gain_map_encodedwith a foreignformatis rejected (the documented mismatch error — any error, it is the codec’s own).- Decoder declared ⇒
probe()reports the map (gain_mappresence notAbsent, and whenAvailableits geometry/channels/params match;supplements.gain_mapset); the defaultBaseOnlydecode carries noDecodedGainMapextra (opt-in only) and its base pixels equal the input when the encoder is lossless;Componentssurfaces aDecodedGainMapwhose geometry, channels, params (exact), alternate CICP and pixels (byte-exact when lossless, else within a mean-abs-error sanity bound) match;with_extract_gain_map(true)yields the identical map;ReconstructHdr { None }withoutreconstructs_hdreither surfaces the components with the base still labelled SDR, or fails withUnsupportedOperation— never an SDR buffer labelled PQ/HLG; withreconstructs_hdrit must succeed with an HDR-labelled buffer and the envelope (mastering_display+content_light_level) onsource_color. - Transcode (Phase 4): the
Componentsmap is fed back through a freshwith_gain_map_pixels, decoded again, and must match the first generation (metadata exactly; pixels byte-exact when lossless). push_rowspath (when the encoder declares it): the same map attached to an incrementalpush_rows+finishencode surfaces identically — the streaming encoder is a separate code path in real codecs, and a job-level setting is easy to leave behind there.- Decoder undeclared ⇒ a
Componentsdecode of the same file either decodes the base with noDecodedGainMapextra (a hidden capability is a lie) or fails withUnsupportedOperation.
Skipped (Ok) only for the undeclared/undeclared pair once the loud
rejection is verified. All violations across the matrix are collected and
reported together. Not covered: the own-format with_gain_map_encoded
fast path (the payload shape is container-specific — a bare AV1 OBU vs a
whole JPEG — so a codec tests it with its own fixture), 10/12-bit maps, and
the positive reconstructs_hdr branch against the testkit’s own codecs
(the reference declines to reconstruct, as zencodec carries no HDR math).
Part of check_all.