imazen / imazen/zenpipe

Cross-codec metadata alignment: 4 gaps surfaced by the conformance suite

Open
#36 0 comments 0 reactions 1 assignee Claimed by @lilith View on GitHub
Dominant language
Rust
Stars
2
Forks
0
PR merge metrics
No merged PRs in 30d

Description

The new cross-codec metadata conformance suite (`zencodecs/tests/metadata_conformance.rs`)
holds every enabled codec to the same `zencodec::Metadata` → encode → decode → `ImageInfo`
contract. It is green today by recording the **observed** behavior, but four cells are marked
`V::Gap` — they *should* round-trip and don't. The suite asserts each gap currently fails; when
one is fixed, the corresponding test trips and forces a `Gap → Ok` promotion in the table, so
this list cannot silently drift.

Observed support matrix (unified `EncodeRequest`/`DecodeRequest` path):

```
codec icc exif_blob orient(exif) orient(field) xmp cicp
jpeg byte-eq yes yes GAP yes n/a
png byte-eq yes GAP GAP yes yes
webp byte-eq yes yes GAP yes n/a
gif n/a n/a n/a n/a n/a n/a
avif byte-eq GAP yes yes yes GAP
jxl reencoded yes GAP GAP yes GAP
```

### Gap 1 — `Metadata::orientation` not emitted to the carrier (jpeg/png/webp/jxl)
`EncodeRequest::with_metadata(meta.with_orientation(..))` only reaches the bitstream for AVIF
(irot/imir). For the other formats the canonical orientation field is dropped — callers must
hand-craft an EXIF orientation tag to set rotation. Blocks the "inject orientation uniformly"
use case. Needs the EXIF write path (zencodec) plus per-codec emission.

### Gap 2 — EXIF orientation not normalized on decode (png/jxl)
PNG and JXL carry the EXIF blob through a round-trip but leave `info.orientation = Identity`;
JPEG/WebP/AVIF normalize the tag. A PNG/JXL with EXIF orientation renders unrotated through the
unified path while the equivalent JPEG renders rotated — an inconsistency in the shared contract.

### Gap 3 — CICP not wired for native-carrier formats (avif/jxl)
Only PNG round-trips `Metadata::cicp` (cICP chunk). AVIF has a native nclx `colr` box and JXL has
codestream color signaling, yet both drop `Metadata::cicp` through encode/decode.

### Gap 4 — AVIF drops the raw EXIF blob
AVIF absorbs orientation into irot but `metadata().exif` is `None` after decode, so copyright,
datetime, camera, and any other EXIF fields are lost on an AVIF round-trip.

### Transcode consequences (also asserted by the suite)
- Copyright **does** transfer between all EXIF-carrying codecs (jpeg/png/webp/jxl).
- Orientation transfers `jpeg→{webp,avif}` and `png→{jpeg,webp,avif}` (blob/field routes) but is
**lost** into png/jxl (Gap 2) and from avif (Gap 4) — see `predict_orientation_transfer`.

### Doc drift noticed
`zencodecs/CLAUDE.md` still says AVIF decode extracts no metadata, but the suite shows AVIF now
round-trips ICC and XMP. The per-codec metadata table in that doc should be refreshed from the
suite's matrix.

Each fix should flip the relevant `V::Gap` to `V::Ok` in `codecs()` once the test confirms the
behavior — the suite is the regression gate.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.