Skip to content

feat(color): cross-codec color-emission policy (resolve_color_emit)#21

Closed
lilith wants to merge 1 commit into
feat/metadata-policyfrom
feat/emit-model
Closed

feat(color): cross-codec color-emission policy (resolve_color_emit)#21
lilith wants to merge 1 commit into
feat/metadata-policyfrom
feat/emit-model

Conversation

@lilith
Copy link
Copy Markdown
Member

@lilith lilith commented Jun 1, 2026

Rescoped (was: "unified scenario-driven encode-emit model"). After dogfooding the over-built design into 5 codecs, an adversarial review, and a full read of the zenpixels/zenpipe color/transcode surface, the grounded conclusion is that the only thing that needs to be shared across codecs is a pure color-carrier policy — and that the scenario/EmitFacts model + a TranscodeEncoder trait were wrong (nothing produces their inputs; the trait would force every codec to depend on every other).

What this is

zencodec::color::resolve_color_emit(&SourceColor, &EncodeCapabilities, ColorPolicy) -> ColorPlan — pure no_std, no CMS, no codec dependencies. It decides which color carriers (ICC vs CICP) to write for a target; the bytes are materialized one layer up via zenpixels_convert::finalize_for_output_with.

This is the shipped #19 shape plus the four surviving red-team fixes:

  1. ColorFields::newColorPolicy::Custom is constructible downstream.
  2. cicp_is_valid_carrier tier → PNG/WebP emit cICP under Balanced (instead of laundering wide-gamut through a synthesized ICC).
  3. No redundant SynthesizeFrom(sRGB) (the canned-profile table returns None for sRGB).
  4. helpers::set_exif_orientation closes the double-rotation hazard (offset-preserving inline tag rewrite, applied by the pipeline).

SynthesizeFrom lowers to icc_profile_for_primaries (a const fn table) — no CMS, never a silent color drop.

What's intentionally NOT here (recorded in docs/color-emit-model.md)

  • No EmitFacts/EmitIntent/EmitPlan scenario model — nothing in the pipeline produces a ColorOrigin/fidelity; the carrier is a flat Metadata.
  • No TranscodeEncoder trait — the ~2 real lossless pairs (JPEG→JPEG, JPEG→JXL) are each self-contained in one crate; zenpipe (deps-all) dispatches them.
  • The zenpipe transcode-only dispatcher (wiring/generalizing try_lossless_jpeg) is a separate later piece.

Status

472 lib tests + 16 doctests pass, clippy + fmt clean. Supersedes the closed #19/#20. Stacked on #17 (feat/metadata-policy); retarget to main once #17 merges.

A pure no_std color-carrier policy: resolve_color_emit(&SourceColor,
&EncodeCapabilities, ColorPolicy) -> ColorPlan{cicp, icc} — no CMS, no codec deps.

Replaces the over-built EmitFacts/EmitIntent/EmitPlan "scenario" model and the
TranscodeEncoder trait, which a 5-codec dogfood + adversarial review + a full
read of zenpixels/zenpipe showed (a) nothing in the pipeline produces the facts
for (decode attaches no color to the buffer; the carrier is a flat Metadata), and
(b) would have forced every codec to depend on every other. The grounded surface
is the shipped #19 shape + the four surviving red-team fixes.

- ColorPolicy { Compatibility, Balanced(default), Compact, Verbatim, Custom };
  ColorPlan { cicp, icc: IccDisposition{KeepSource, SynthesizeFrom, Drop} }.
- EncodeCapabilities: cicp_is_valid_carrier (standardized carrier incl. PNG cICP),
  cicp_safe_sole_carrier (JXL only). IccRetention +DropIfCicpRepresentable,
  +DropIfCicpSafeSoleCarrier. ColorFields::new makes Custom constructible.
- No redundant SynthesizeFrom(sRGB). Lowers to zenpixels_convert::
  finalize_for_output_with; SynthesizeFrom -> icc_profile_for_primaries const-fn
  table (no CMS, no silent drop; sRGB -> None).
- helpers::set_exif_orientation closes the double-rotation hazard (pipeline-applied).

472 lib tests + 16 doctests pass, clippy + fmt clean. Design + rejected
alternatives recorded in docs/color-emit-model.md.
@lilith lilith force-pushed the feat/emit-model branch from 03fb6eb to bceda85 Compare June 2, 2026 02:25
@lilith lilith changed the title feat(emit): unified scenario-driven encode-emit model (replaces #19, #20) feat(color): cross-codec color-emission policy (resolve_color_emit) Jun 2, 2026
@lilith lilith closed this Jun 2, 2026
@lilith lilith deleted the feat/emit-model branch June 2, 2026 03:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant