pub trait PluggableCms: Send + Sync {
// Required method
fn build_source_transform(
&self,
src: ColorProfileSource<'_>,
dst: ColorProfileSource<'_>,
src_format: PixelFormat,
dst_format: PixelFormat,
options: &ConvertOptions,
) -> Option<Result<Box<dyn RowTransformMut>, At<CmsPluginError>>>;
// Provided method
fn build_shared_source_transform(
&self,
_src: ColorProfileSource<'_>,
_dst: ColorProfileSource<'_>,
_src_format: PixelFormat,
_dst_format: PixelFormat,
_options: &ConvertOptions,
) -> Option<Result<Arc<dyn RowTransform>, At<CmsPluginError>>> { ... }
}Expand description
Dyn-compatible CMS plugin interface for overriding gamut/profile
conversions inside a ConvertPlan.
When a PluggableCms is passed to
RowConverter::new_explicit_with_cms
and the source and destination profiles differ, the plan asks the
plugin whether it will handle the exact (src_format, dst_format)
pair. If the plugin returns a transform, the plan collapses to a
single external-transform step that drives the row end-to-end —
built-in linearize → gamut-matrix → encode steps (and their fused
matlut kernels) are bypassed for that conversion. If the plugin
returns None, the plan falls back to the built-in path.
PluggableCms is intentionally narrower than ColorManagement:
- It accepts
ColorProfileSourceinstead of raw ICC bytes, so plugins can use primaries/transfer shortcuts, named profiles, CICP, or ICC without forcing the caller to serialize to ICC. - It receives
ConvertOptionsso plugins can honorclip_out_of_gamutand future fields like rendering intent. - It is dyn-compatible (no associated
Errortype; no generics). This is what lets it live behind&dyn PluggableCmsin API signatures without forcing every caller to monomorphize.
§Decline vs. fail
Plugin methods return Option<Result<T, CmsPluginError>> with three
outcomes:
None— declined (“not my problem”). The dispatch chain continues to the next plugin (typicallyZenCmsLite) or falls through to the built-in path.Some(Ok(transform))— accepted. The dispatch chain stops here.Some(Err(e))— tried-and-failed. The error propagates immediately; the chain does not continue. If a plugin took ownership of a conversion and failed, we surface that rather than silently producing different output from a fallback backend.
Required Methods§
Sourcefn build_source_transform(
&self,
src: ColorProfileSource<'_>,
dst: ColorProfileSource<'_>,
src_format: PixelFormat,
dst_format: PixelFormat,
options: &ConvertOptions,
) -> Option<Result<Box<dyn RowTransformMut>, At<CmsPluginError>>>
fn build_source_transform( &self, src: ColorProfileSource<'_>, dst: ColorProfileSource<'_>, src_format: PixelFormat, dst_format: PixelFormat, options: &ConvertOptions, ) -> Option<Result<Box<dyn RowTransformMut>, At<CmsPluginError>>>
Attempt to build an owned, stateful row transform covering the full source → destination conversion for the given pixel formats.
options carries policy flags the plugin may honor (e.g.,
clip_out_of_gamut). The plugin is free to ignore fields that
don’t apply to its implementation.
See the trait docs for decline vs. fail semantics.
The Err arm is whereat::At<CmsPluginError> so the plugin’s
internal failure point is recorded for debugging. Use
whereat::at! or ResultAtExt::at() to construct.
Provided Methods§
Optionally build a shareable, stateless row transform for the same conversion.
When the transform carries no per-call mutable state, returning
Arc<dyn RowTransform> enables sharing across threads, caching for
batch workloads, and cheap RowConverter clones. Default returns
None — plugins without a stateless fast path fall through to the
owned build_source_transform.
RowConverter::new_explicit_with_cms tries this method first.
See the trait docs for decline vs. fail semantics. Err arm is
whereat::At<CmsPluginError> — same location-tracking semantics
as build_source_transform.