feat: Fidelity API — generic lossy/near-lossless/lossless encode quality (#12)#22
Open
lilith wants to merge 1 commit into
Open
feat: Fidelity API — generic lossy/near-lossless/lossless encode quality (#12)#22lilith wants to merge 1 commit into
lilith wants to merge 1 commit into
Conversation
…ity (#12) Sum-type fidelity abstraction on the EncoderConfig surface: - Fidelity { Lossy(LossyTarget), NearLossless(NearLosslessBudget), Lossless } - LossyTarget (non-exhaustive): Quality / Distance / Metric{QualityMetric,target} / TargetBytes / Bitrate — arms differ in cost/support - NearLosslessBudget(u16): codec-agnostic max per-channel L-infinity error as a parts-per-65535 fraction; exact at 8- and 16-bit via max_error_at_depth - FidelityMatch: Supported / MetricTranslated / TargetRaised / TargetLowered / Lossless / Unsupported (returned by try_target_fidelity) - QualityMetric (non-exhaustive): Ssimulacra2 / Butteraugli / Dssim / Psnr EncoderConfig gains with_fidelity (infallible, best-effort, chainable), try_target_fidelity (fail-fast, returns FidelityMatch), resolved_target_fidelity, with_alpha_fidelity/alpha_fidelity. EncodeCapabilities gains near_lossless + supports_{distance,metric_target,size_target}. Default impls bridge to the legacy with_generic_quality/with_lossless scalars both ways, so a codec implements either pair and gets the other free — additive, non-breaking. Codec impls land separately. Design + per-codec mapping: docs/near-lossless-design.md
Member
Author
|
Closing per request. The design and types remain captured in |
Member
Author
|
Reopened — my misread; the close was meant for the standalone |
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.
Implements the generic encode-quality abstraction from #12 — the converged design from the discussion on that issue.
What this adds (zencodec types +
EncoderConfigsurface)Fidelityis a sum type — exactly one of lossy, near-lossless, or lossless — so each regime carries the parameter its own metric needs, illegal states (lossy ∧ lossless) are unrepresentable, and lossless is explicit (notquality == 100, which is a footgun on JPEG).NearLosslessBudgetis a codec-agnostic max-error fraction (every value valid for every lossless codec).255 × 257 = 65535makes 8- and 16-bit both exact:from_8bit_steps(2)→±2at 8-bit,±514at 16-bit, no float-floor trap. Codecs consumemax_error_at_depth(depth)and round the guarantee down.EncoderConfigmethodstry_target_fidelityreturnsFidelityMatch—Supported/MetricTranslated/TargetRaised/TargetLowered/Lossless/Unsupported. A codec may quietly give you better fidelity than asked (TargetRaised,Lossless) but never silently less — a downgrade across the lossy/lossless fence isUnsupported.EncodeCapabilitiesgainsnear_lossless,supports_distance,supports_metric_target,supports_size_target.Back-compat
Additive, non-breaking. Default impls bridge to the legacy
with_generic_quality/with_losslessscalars both ways, so a codec implements either the legacy pair or the newwith_fidelity/resolved_target_fidelitypair and gets the other for free. NoDynEncoderConfigchange (fidelity is set on the concrete config before type-erasure, like quality/lossless today).Out of scope (follow-ups, each in its own codec crate)
caps.near_lossless = true; AVIF/GIF/JXL promoteNearLossless→Lossless; JPEG leaves the default.LossyTargetarms (Distance/Metric/TargetBytes/Bitrate) land with their capability flags +FidelityMatchreporting.Verification
cargo test— 10 unit tests for the budget math / classification + doctests, all passcargo clippy --all-targets -D warnings— cleancargo fmt --check— cleancargo doc— clean (the only-D warningsdoc-link failures are pre-existing ingainmap.rs/limits.rs, untouched here)Design rationale + per-codec mapping:
docs/near-lossless-design.md(rewritten in this PR; supersedes the standalonedocs/near-lossless-designbranch).