pub struct IccCache { /* private fields */ }Expand description
ICC color profile cache and transform manager.
Implementations§
Source§impl IccCache
impl IccCache
Sourcepub fn new() -> Self
pub fn new() -> Self
Create an empty ICC cache with default options (BPC Auto, no
pre-supplied source CMYK profile).
Sourcepub fn new_with_options(opts: IccCacheOptions) -> Self
pub fn new_with_options(opts: IccCacheOptions) -> Self
Create an ICC cache with the given options.
When opts.source_cmyk_profile is Some, the bytes are registered as
the system CMYK profile (overriding any later
Self::search_system_cmyk_profile call). Otherwise the cache starts
empty and the caller is expected to supply a profile separately.
Examples found in repository?
58fn main() {
59 let path = std::env::args()
60 .nth(1)
61 .expect("usage: icc_probe <profile.icc>");
62 let bytes = std::fs::read(&path).expect("read profile");
63 dump_profile_shape(&bytes);
64 let cases: &[(f64, f64, f64, f64)] = &[
65 (0.15, 1.0, 1.0, 0.0),
66 (0.0, 0.6, 1.0, 0.0),
67 (0.0, 0.5, 0.9, 0.0),
68 (0.0, 0.7, 1.0, 0.0),
69 (0.15, 0.7, 1.0, 0.0),
70 (0.0, 1.0, 1.0, 0.0),
71 (0.0, 0.0, 0.0, 1.0),
72 (0.0, 0.0, 0.0, 0.0),
73 // Medium-light green range — covers the 0001056.pdf glove regression.
74 (0.15, 0.05, 0.30, 0.0),
75 (0.25, 0.10, 0.40, 0.0),
76 (0.40, 0.15, 0.50, 0.0),
77 (0.40, 0.0, 1.0, 0.0),
78 (0.60, 0.0, 0.80, 0.0),
79 (0.20, 0.20, 0.20, 0.0),
80 // Process primaries — likely out of sRGB gamut.
81 (1.0, 0.0, 0.0, 0.0),
82 (0.0, 1.0, 0.0, 0.0),
83 (0.0, 0.0, 1.0, 0.0),
84 (1.0, 1.0, 0.0, 0.0),
85 ];
86 for mode in [BpcMode::Off, BpcMode::On] {
87 println!("\n== BPC {:?} ==", mode);
88 let opts = IccCacheOptions {
89 bpc_mode: mode,
90 source_cmyk_profile: Some(bytes.clone()),
91 };
92 let cache = IccCache::new_with_options(opts);
93 for &(c, m, y, k) in cases {
94 let rgb = cache.convert_cmyk_readonly(c, m, y, k).expect("convert");
95 println!(
96 " CMYK({:.2},{:.2},{:.2},{:.2}) -> ({}, {}, {})",
97 c,
98 m,
99 y,
100 k,
101 (rgb.0 * 255.0).round() as u8,
102 (rgb.1 * 255.0).round() as u8,
103 (rgb.2 * 255.0).round() as u8,
104 );
105 }
106 }
107}Sourcepub fn hash_profile(bytes: &[u8]) -> ProfileHash
pub fn hash_profile(bytes: &[u8]) -> ProfileHash
Compute the SHA-256 hash of an ICC profile without registering it.
Sourcepub fn register_profile(&mut self, bytes: &[u8]) -> Option<ProfileHash>
pub fn register_profile(&mut self, bytes: &[u8]) -> Option<ProfileHash>
Register an ICC profile from raw bytes. Returns the SHA-256 hash on success.
Sourcepub fn register_profile_with_n(
&mut self,
bytes: &[u8],
expected_n: Option<u32>,
) -> Option<ProfileHash>
pub fn register_profile_with_n( &mut self, bytes: &[u8], expected_n: Option<u32>, ) -> Option<ProfileHash>
Register an ICC profile, validating that its color space matches the
expected component count expected_n. When the profile’s actual color
space has a different number of components (e.g. an RGB profile stored
with PDF /N 1), the profile is rejected so the caller can fall back
to the alternate color space.
Sourcepub fn convert_to_oi_cmyk(
&self,
hash: &ProfileHash,
components: &[f64],
intent: RenderingIntent,
) -> Option<[f64; 4]>
pub fn convert_to_oi_cmyk( &self, hash: &ProfileHash, components: &[f64], intent: RenderingIntent, ) -> Option<[f64; 4]>
Convert RGB components through the proofing chain’s stage 1 to
the OutputIntent’s CMYK ink values. Returns None when no
hand-rolled chain exists for this profile (the document isn’t
PDF/X, or the profile shape is unsupported), in which case the
caller should leave DeviceColor::native_cmyk as None and the
renderer falls back to its sRGB-derived approximation. The
intent parameter selects which per-intent chain to use; falls
back to the Perceptual chain when the requested intent slot is
empty.
Sourcepub fn convert_color(
&mut self,
hash: &ProfileHash,
components: &[f64],
) -> Option<(f64, f64, f64)>
pub fn convert_color( &mut self, hash: &ProfileHash, components: &[f64], ) -> Option<(f64, f64, f64)>
Convert a single color through an ICC profile to sRGB. Returns (r, g, b) in [0, 1] range.
Sourcepub fn convert_color_with_intent(
&mut self,
hash: &ProfileHash,
components: &[f64],
intent: RenderingIntent,
) -> Option<(f64, f64, f64)>
pub fn convert_color_with_intent( &mut self, hash: &ProfileHash, components: &[f64], intent: RenderingIntent, ) -> Option<(f64, f64, f64)>
Cached single-color conversion under a specific rendering
intent. Delegates to the legacy Self::convert_color for
Perceptual (which uses the Perceptual chain stored in
transform_f64 and the Perceptual-keyed cache); for the other
intents it goes through Self::convert_color_readonly_with_intent
and caches per-intent.
Sourcepub fn convert_color_readonly_with_intent(
&self,
hash: &ProfileHash,
components: &[f64],
intent: RenderingIntent,
) -> Option<(f64, f64, f64)>
pub fn convert_color_readonly_with_intent( &self, hash: &ProfileHash, components: &[f64], intent: RenderingIntent, ) -> Option<(f64, f64, f64)>
Convert a single color through an ICC profile using a specific
rendering intent. Falls back to the cached default chain (built
from the Perceptual tables) when no per-intent chain is
available — that path matches Self::convert_color_readonly
byte-for-byte and is the common case for non-PDF/X documents and
CMYK source profiles.
Sourcepub fn convert_color_readonly(
&self,
hash: &ProfileHash,
components: &[f64],
) -> Option<(f64, f64, f64)>
pub fn convert_color_readonly( &self, hash: &ProfileHash, components: &[f64], ) -> Option<(f64, f64, f64)>
Convert a single color through an ICC profile (read-only, no caching).
Same as convert_color but takes &self instead of &mut self,
suitable for use from immutable contexts like rendering.
Sourcepub fn convert_image_8bit_with_intent(
&self,
hash: &ProfileHash,
samples: &[u8],
pixel_count: usize,
intent: RenderingIntent,
) -> Option<Vec<u8>>
pub fn convert_image_8bit_with_intent( &self, hash: &ProfileHash, samples: &[u8], pixel_count: usize, intent: RenderingIntent, ) -> Option<Vec<u8>>
Bulk-convert 8-bit image samples through an ICC profile to RGB
using a specific rendering intent. Falls back to the cached
default 8-bit transform (built from the Perceptual tables) when
no per-intent chain is available — that path matches
Self::convert_image_8bit byte-for-byte.
Sourcepub fn convert_image_8bit(
&self,
hash: &ProfileHash,
samples: &[u8],
pixel_count: usize,
) -> Option<Vec<u8>>
pub fn convert_image_8bit( &self, hash: &ProfileHash, samples: &[u8], pixel_count: usize, ) -> Option<Vec<u8>>
Bulk-convert 8-bit image samples through an ICC profile to RGB. Input: packed samples (Gray/RGB/CMYK depending on profile). Output: packed RGB bytes (3 bytes per pixel).
Sourcepub fn search_system_cmyk_profile(&mut self)
pub fn search_system_cmyk_profile(&mut self)
Search system paths for a CMYK ICC profile and register it.
Sourcepub fn load_cmyk_profile_bytes(&mut self, bytes: &[u8])
pub fn load_cmyk_profile_bytes(&mut self, bytes: &[u8])
Load a CMYK ICC profile from raw bytes (for environments without filesystem access).
Sourcepub fn default_cmyk_hash(&self) -> Option<&ProfileHash>
pub fn default_cmyk_hash(&self) -> Option<&ProfileHash>
Get the default CMYK profile hash, if a system CMYK profile was found.
Sourcepub fn has_profile(&self, hash: &ProfileHash) -> bool
pub fn has_profile(&self, hash: &ProfileHash) -> bool
Check if a profile hash has been registered.
Sourcepub fn get_profile_bytes(&self, hash: &ProfileHash) -> Option<Arc<Vec<u8>>>
pub fn get_profile_bytes(&self, hash: &ProfileHash) -> Option<Arc<Vec<u8>>>
Get the raw bytes of a registered ICC profile (for PDF embedding).
Sourcepub fn system_cmyk_bytes(&self) -> Option<&Arc<Vec<u8>>>
pub fn system_cmyk_bytes(&self) -> Option<&Arc<Vec<u8>>>
Get the raw bytes of the system CMYK profile (for re-registration in render threads).
Sourcepub fn set_system_cmyk(&mut self, bytes: &[u8], hash: ProfileHash)
pub fn set_system_cmyk(&mut self, bytes: &[u8], hash: ProfileHash)
Set the system CMYK profile from pre-loaded bytes and hash.
Used by --output-profile to substitute the auto-detected system CMYK
profile with a user-specified one.
Sourcepub fn set_proofing_enabled(&mut self, enabled: bool)
pub fn set_proofing_enabled(&mut self, enabled: bool)
Enable PDF/X-style proofing: ICCBased profiles registered while this
flag is set route through the default CMYK profile (the OutputIntent)
before reaching sRGB. See Self::proofing_enabled.
Sourcepub fn proofing_enabled(&self) -> bool
pub fn proofing_enabled(&self) -> bool
Whether PDF/X-style proofing is enabled. When true, source ICC
profiles other than the default CMYK convert through the default
CMYK (“OutputIntent”) instead of going directly to sRGB. This makes
per-swatch ICC colours and surrounding DeviceCMYK paints converge
through the same final OutputIntent → sRGB stage. When false,
every profile converts directly (the historical behaviour).
Sourcepub fn set_default_cmyk_hash(&mut self, hash: ProfileHash)
pub fn set_default_cmyk_hash(&mut self, hash: ProfileHash)
Set the default CMYK profile hash (used when building render-thread caches).
Sourcepub fn suspend_default_cmyk(&mut self) -> Option<ProfileHash>
pub fn suspend_default_cmyk(&mut self) -> Option<ProfileHash>
Temporarily remove the default CMYK hash, returning the old value. Used to disable ICC CMYK conversion inside soft mask form rendering, where PLRM formulas produce correct luminosity values (ICC profiles map 100% K to non-zero RGB, breaking luminosity soft masks).
Sourcepub fn restore_default_cmyk(&mut self, hash: Option<ProfileHash>)
pub fn restore_default_cmyk(&mut self, hash: Option<ProfileHash>)
Restore a previously suspended default CMYK hash.
Sourcepub fn convert_cmyk(
&mut self,
c: f64,
m: f64,
y: f64,
k: f64,
) -> Option<(f64, f64, f64)>
pub fn convert_cmyk( &mut self, c: f64, m: f64, y: f64, k: f64, ) -> Option<(f64, f64, f64)>
Convert CMYK to (r, g, b) using the default system CMYK profile. Returns None if no system CMYK profile is loaded.
Sourcepub fn convert_cmyk_readonly(
&self,
c: f64,
m: f64,
y: f64,
k: f64,
) -> Option<(f64, f64, f64)>
pub fn convert_cmyk_readonly( &self, c: f64, m: f64, y: f64, k: f64, ) -> Option<(f64, f64, f64)>
Convert CMYK to (r, g, b) using the default system CMYK profile (read-only, no caching).
Used by band renderers that only have &self access.
Examples found in repository?
58fn main() {
59 let path = std::env::args()
60 .nth(1)
61 .expect("usage: icc_probe <profile.icc>");
62 let bytes = std::fs::read(&path).expect("read profile");
63 dump_profile_shape(&bytes);
64 let cases: &[(f64, f64, f64, f64)] = &[
65 (0.15, 1.0, 1.0, 0.0),
66 (0.0, 0.6, 1.0, 0.0),
67 (0.0, 0.5, 0.9, 0.0),
68 (0.0, 0.7, 1.0, 0.0),
69 (0.15, 0.7, 1.0, 0.0),
70 (0.0, 1.0, 1.0, 0.0),
71 (0.0, 0.0, 0.0, 1.0),
72 (0.0, 0.0, 0.0, 0.0),
73 // Medium-light green range — covers the 0001056.pdf glove regression.
74 (0.15, 0.05, 0.30, 0.0),
75 (0.25, 0.10, 0.40, 0.0),
76 (0.40, 0.15, 0.50, 0.0),
77 (0.40, 0.0, 1.0, 0.0),
78 (0.60, 0.0, 0.80, 0.0),
79 (0.20, 0.20, 0.20, 0.0),
80 // Process primaries — likely out of sRGB gamut.
81 (1.0, 0.0, 0.0, 0.0),
82 (0.0, 1.0, 0.0, 0.0),
83 (0.0, 0.0, 1.0, 0.0),
84 (1.0, 1.0, 0.0, 0.0),
85 ];
86 for mode in [BpcMode::Off, BpcMode::On] {
87 println!("\n== BPC {:?} ==", mode);
88 let opts = IccCacheOptions {
89 bpc_mode: mode,
90 source_cmyk_profile: Some(bytes.clone()),
91 };
92 let cache = IccCache::new_with_options(opts);
93 for &(c, m, y, k) in cases {
94 let rgb = cache.convert_cmyk_readonly(c, m, y, k).expect("convert");
95 println!(
96 " CMYK({:.2},{:.2},{:.2},{:.2}) -> ({}, {}, {})",
97 c,
98 m,
99 y,
100 k,
101 (rgb.0 * 255.0).round() as u8,
102 (rgb.1 * 255.0).round() as u8,
103 (rgb.2 * 255.0).round() as u8,
104 );
105 }
106 }
107}Sourcepub fn prepare_reverse_cmyk(&mut self)
pub fn prepare_reverse_cmyk(&mut self)
Pre-warm the lazy sRGB→CMYK reverse transform. Should be called once on
the build thread that owns &mut IccCache, after the system CMYK
profile has been registered, so that band renderers (which only hold
&IccCache) can use Self::convert_rgb_to_cmyk_readonly without
having to mutate state.
Sourcepub fn prepare_lab_to_oi_cmyk(&mut self)
pub fn prepare_lab_to_oi_cmyk(&mut self)
Pre-build per-intent Lab → OutputIntent CMYK samplers from the
document’s OutputIntent profile. Call once after the OI is registered
so Self::convert_lab_to_oi_cmyk can run from &IccCache.
No-op when no default CMYK profile is registered, when the profile
shape doesn’t expose B2A LUTs (shaper-matrix CMYK with no LUT, etc.),
or when proofing is disabled.
Sourcepub fn convert_lab_to_oi_cmyk(
&self,
l_star: f64,
a_star: f64,
b_star: f64,
intent: IccRenderingIntent,
) -> Option<[f64; 4]>
pub fn convert_lab_to_oi_cmyk( &self, l_star: f64, a_star: f64, b_star: f64, intent: IccRenderingIntent, ) -> Option<[f64; 4]>
Convert a PDF Lab triplet (L* ∈ [0, 100], a*/b* ∈ [-128, 127]) to
OutputIntent CMYK using the OI’s per-intent B2A table. Returns None
when the per-intent sampler hasn’t been built (call
Self::prepare_lab_to_oi_cmyk first) or when the intent slot is
empty (falls back to Perceptual when available).
Used by lab_to_device_color to populate DeviceColor::native_cmyk
so the renderer’s parallel CMYK buffer holds the same direct
Lab → OI CMYK value Acrobat’s ACE produces. Without this, the
renderer falls back to convert_rgb_to_cmyk_readonly (sRGB → ICC
reverse), which drifts visibly under CMYK-group blends. GWG 22.1’s
ColorBurn form over a Lab BG is the canonical surfacing case.
Sourcepub fn convert_rgb_to_cmyk_readonly(
&self,
r: f64,
g: f64,
b: f64,
) -> Option<[f64; 4]>
pub fn convert_rgb_to_cmyk_readonly( &self, r: f64, g: f64, b: f64, ) -> Option<[f64; 4]>
Convert an sRGB color to CMYK using the system CMYK profile, without
mutating any state. Returns None when the reverse transform has not
been pre-built (call Self::prepare_reverse_cmyk first) or when no
system CMYK profile is registered.
The returned components are clamped to [0, 1].
Sourcepub fn round_trip_rgb_via_cmyk(
&mut self,
r: f64,
g: f64,
b: f64,
) -> Option<(f64, f64, f64)>
pub fn round_trip_rgb_via_cmyk( &mut self, r: f64, g: f64, b: f64, ) -> Option<(f64, f64, f64)>
Round-trip an RGB color through the system CMYK profile: sRGB→CMYK→sRGB. Used when compositing in a DeviceCMYK page group — saturated RGB colors become more muted after passing through the CMYK gamut. Returns None if no CMYK profile is loaded.