feat(color): cross-codec color-emission policy (resolve_color_emit)#21
Closed
lilith wants to merge 1 commit into
Closed
feat(color): cross-codec color-emission policy (resolve_color_emit)#21lilith wants to merge 1 commit into
lilith wants to merge 1 commit into
Conversation
This was referenced Jun 1, 2026
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/
EmitFactsmodel + aTranscodeEncodertrait 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— pureno_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 viazenpixels_convert::finalize_for_output_with.This is the shipped #19 shape plus the four surviving red-team fixes:
ColorFields::new→ColorPolicy::Customis constructible downstream.cicp_is_valid_carriertier → PNG/WebP emitcICPunder Balanced (instead of laundering wide-gamut through a synthesized ICC).SynthesizeFrom(sRGB)(the canned-profile table returnsNonefor sRGB).helpers::set_exif_orientationcloses the double-rotation hazard (offset-preserving inline tag rewrite, applied by the pipeline).SynthesizeFromlowers toicc_profile_for_primaries(aconst fntable) — no CMS, never a silent color drop.What's intentionally NOT here (recorded in
docs/color-emit-model.md)EmitFacts/EmitIntent/EmitPlanscenario model — nothing in the pipeline produces aColorOrigin/fidelity; the carrier is a flatMetadata.TranscodeEncodertrait — the ~2 real lossless pairs (JPEG→JPEG, JPEG→JXL) are each self-contained in one crate; zenpipe (deps-all) dispatches them.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 tomainonce #17 merges.