imazen / imazen/zencodec

Format-agnostic consumer checklist: contracts + APIs that eliminate per-format special casing

Open
#27 2 comments 0 reactions 1 assignee View on GitHub

@lilith is already working on this.

Since Jun 12, 2026.

Dominant language
Rust
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Description

Distilled from the hdr-corpus-convert v3 migration (the tool now runs on the trait adapters; this is what's left between consumers and zero per-format code). Items 2-4 are small; 1 and 5-6 are design decisions.

  1. Composition/registry story. zencodec cannot name codec types (dependency direction), so "decode whatever these bytes are" needs either the zencodecs registry's heic-decode feature finished, or a registration builder here over the existing dyn_decoding traits: the app lists codec configs once; detection + dispatch become registry.probe(bytes) / registry.job(format). This removes the only place consumers enumerate formats (today: try PngDecoderConfigJpegDecoderConfigHeicDecoderConfig probes in order).

  2. Contract: Supplements/GainMapPresence population is mandatory on probe and decode ImageInfo, with a conformance test. heic populates it; zenjpeg only since imazen/zenjpeg@94fb6ec6. Format-agnostic consumers gate their ReconstructHdr pass on it — a codec that omits it silently loses HDR.

  3. Contract: GainMapRender::ReconstructHdr on gain-map-less input returns the base rendition. zenjpeg falls through to the base ("the image IS the image"); heic errors. Specify the zenjpeg behavior in the GainMapRender docs, align heic, add a conformance case. The asymmetry is why consumers need the supplements gate defensively.

  4. orientation_applied on full-decode info. Push decode's OutputInfo has with_orientation_applied; full decode reports Identity under Correct with no record of what was baked. Consumers re-parse EXIF just to log/report the applied transform.

  5. Resolved-color authority contract. Adapters surface raw container color and consumers resolve (e.g. Apple's "unspecified nclx + ICC ⇒ Display P3" lives in hdr-corpus-convert today). Contract should be: decoded descriptor/source_color carries FINAL resolved CICP, container-specific rules included — the Apple rule belongs in the heic adapter next to the container knowledge. Machinery exists (descriptor_for_decoded_pixels_v2, zenpixels::icc::identify_common, ColorAuthority); the obligation doesn't.

  6. Required (not preferred) output-descriptor negotiation. preferred is a hint, so consumers carry conversion fallbacks (gray JPEGs decode natively to Gray8; the corpus tool expands to RGB8 tool-side). A with_required_descriptor mode (convert or error) moves that into adapters — gated on imazen/zenjpeg#154 (zenjpeg's internal gray→RGB rounds ±1 off the gray plane; requiring RGB8 before that fix reintroduces it).

  7. Dual-rendition decode (cost only) — #24 territory: one pass returning base + reconstructed HDR. Gain-mapped files currently decode the base twice (BaseOnly + inside ReconstructHdr).

Encode-side analog of 5: deterministic cicp/cLLI emission through the trait job (today byte-stable PNG output requires zenpng's native EncodeConfig path because the Metadata + color-emit route may synthesize an ICC alongside cICP).

Context: imazen/zenjpeg#151 #152 #154, imazen/heic#20, zencodec#24. The corpus tool's remaining per-format code after this checklist: none (the PNG byte-copy arm becomes info.format == ImageFormat::Png, which is data).

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.