You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
gamut-cmm: option to prefer CICP-signalled transfer characteristics over a profile's TRC tags #555
CICP → IccProfile, plus the transform-side option to prefer CICP-signalled transfer characteristics.
PR #542 landed the constructor half (IccProfile::from_cicp, from_source_profile, builtin, gray_with_gamma). The transform-side option was deliberately not taken there, and is filed here rather than left unrecorded.
What is missing
moxcms exposes TransformOptions::allow_use_cicp_transfer (default true, documented as "more precise and faster"): when a profile carries a cicpType tag (ICC.1:2022 §10.3), the CMM evaluates the H.273 transfer function in closed form instead of interpolating the profile's rTRC/gTRC/bTRC sample tables.
gamut-cmm has no equivalent. The choice belongs there, not in gamut-icc: gamut-icc parses and serializes profiles and explicitly does not evaluate them (see its STATUS.md, "Deferred / intentional leniencies"), while gamut-cmm owns the pipeline/stage model that would select the curve evaluator.
Why it is worth having
Two independent reasons, both measurable rather than assumed:
Precision. A sampled curveType is a uInt16 table read by linear interpolation. Where the profile also signals CICP, the closed form is exact. The strongest case in the workspace today is the BT.2100 PQ built-in profile, whose TRC is 1024 sampled points precisely because §10.18 has no parametric form for ST 2084 — the cicp tag it carries names code point 16, which a CMM could evaluate directly.
Speed. Closed-form evaluation avoids the table lookup and interpolation per sample.
Neither should be taken on the strength of the analogy with moxcms. A benchmark and a ΔE₀₀ measurement against the Little-CMS oracle decide whether the option earns its surface.
Constraints worth stating up front
§10.3 says "the colour encoding specified by the CICP tag content shall be equivalent to the data colour space encoding represented by this ICC profile", but a profile in the wild may violate that. An option that silently prefers the tag changes the rendering of such a profile, so the default matters and has to be argued, not inherited from another implementation.
The transfer functions themselves live in gamut-color (transfer::eotf_for), which supplies no EOTF for several code points a profile may signal — BT.709 (1), BT.601 (6), BT.2020 (14, 15) and HLG (18) among them. gamut-icc can now encode the BT.709 family as a parametric curve but cannot evaluate it either. So the option's reach is bounded by what gamut-color can evaluate, and closing that gap is part of the work (compare gamut-color: expose ColourPrimaries chromaticities and an inverse transfer (oetf_for) #376).
Acceptance
A gamut-cmm transform built from a profile carrying a cicp tag, with the option on, matches Little-CMS's transform through the same profile inside the ΔE₀₀ budgets gamut-cmm's conformance gate already publishes.
A benchmark showing the speed claim, and a measurement showing the precision claim on the PQ profile, or the option is declined and this issue closed with that evidence.
Split out of #424, piece 2. That piece reads:
PR #542 landed the constructor half (
IccProfile::from_cicp,from_source_profile,builtin,gray_with_gamma). The transform-side option was deliberately not taken there, and is filed here rather than left unrecorded.What is missing
moxcms exposes
TransformOptions::allow_use_cicp_transfer(defaulttrue, documented as "more precise and faster"): when a profile carries acicpTypetag (ICC.1:2022 §10.3), the CMM evaluates the H.273 transfer function in closed form instead of interpolating the profile'srTRC/gTRC/bTRCsample tables.gamut-cmmhas no equivalent. The choice belongs there, not ingamut-icc:gamut-iccparses and serializes profiles and explicitly does not evaluate them (see its STATUS.md, "Deferred / intentional leniencies"), whilegamut-cmmowns the pipeline/stage model that would select the curve evaluator.Why it is worth having
Two independent reasons, both measurable rather than assumed:
curveTypeis auInt16table read by linear interpolation. Where the profile also signals CICP, the closed form is exact. The strongest case in the workspace today is the BT.2100 PQ built-in profile, whose TRC is 1024 sampled points precisely because §10.18 has no parametric form for ST 2084 — thecicptag it carries names code point 16, which a CMM could evaluate directly.Neither should be taken on the strength of the analogy with moxcms. A benchmark and a ΔE₀₀ measurement against the Little-CMS oracle decide whether the option earns its surface.
Constraints worth stating up front
gamut-color(transfer::eotf_for), which supplies no EOTF for several code points a profile may signal — BT.709 (1), BT.601 (6), BT.2020 (14, 15) and HLG (18) among them.gamut-icccan now encode the BT.709 family as a parametric curve but cannot evaluate it either. So the option's reach is bounded by whatgamut-colorcan evaluate, and closing that gap is part of the work (compare gamut-color: expose ColourPrimaries chromaticities and an inverse transfer (oetf_for) #376).Acceptance
gamut-cmmtransform built from a profile carrying acicptag, with the option on, matches Little-CMS's transform through the same profile inside the ΔE₀₀ budgetsgamut-cmm's conformance gate already publishes.Refs #424, #542.