Skip to main content

RenderingIntent

Enum RenderingIntent 

Source
pub enum RenderingIntent {
    Perceptual,
    RelativeColorimetric,
    Saturation,
    AbsoluteColorimetric,
}
Expand description

ICC rendering intent — controls how colors outside the destination gamut are handled during a profile-to-profile transform.

§Which intent to use

For display-to-display workflows (web images, app thumbnails, photo export): use RelativeColorimetric. It preserves in-gamut colors exactly and is the de facto standard for screen output.

For photographic print with a profile that has a perceptual table: use Perceptual. It compresses the full source gamut smoothly instead of clipping.

For soft-proofing (“what will this print look like on screen”): use AbsoluteColorimetric to simulate the paper white.

Saturation is for business graphics (pie charts, logos). It is almost never correct for photographic images.

§Interaction with ICC profiles

An ICC profile may contain up to four LUTs (AToB0–AToB3), one per intent. Most display profiles only ship a single LUT (relative colorimetric). When you request an intent whose LUT is absent, the CMS silently falls back to the profile’s default — usually relative colorimetric. This means Perceptual and RelativeColorimetric produce identical output for the vast majority of display profiles (sRGB IEC 61966-2.1, Display P3, etc.). The distinction only matters for print/press profiles that include dedicated perceptual gamut-mapping tables.

§Bugs and pitfalls

  • Perceptual on display profiles is a no-op. Requesting Perceptual doesn’t add gamut mapping when the profile lacks a perceptual table — it silently degrades to clipping. If you need actual gamut mapping between display profiles, you must supply a profile that contains perceptual intent tables (e.g., a proofing profile or a carefully authored display profile).

  • AbsoluteColorimetric tints whites. Source white is preserved literally, so a D50 source on a D65 display shows yellowish whites. Never use this for final output — only for proofing previews.

  • Saturation may shift hues. The ICC spec allows saturation-intent tables to sacrifice hue accuracy for vividness. Photographs will look wrong.

Variants§

§

Perceptual

Compress the entire source gamut into the destination gamut, preserving the perceptual relationship between colors at the cost of shifting all values (including in-gamut ones).

Requires a perceptual LUT in the profile. Most display profiles omit this table, so the CMS falls back to relative colorimetric silently. This intent only behaves differently from RelativeColorimetric when both source and destination profiles contain dedicated perceptual rendering tables — typically print, press, or carefully authored proofing profiles.

When it works: smooth, continuous gamut mapping with no hard clips. When the LUT is missing: identical to RelativeColorimetric.

CMS compatibility warning: moxcms’s perceptual intent implementation does not match lcms2’s output and may not be accurate for all profile combinations. If cross-CMS consistency matters, prefer RelativeColorimetric.

§

RelativeColorimetric

Preserve in-gamut colors exactly; clip out-of-gamut colors to the nearest boundary color. White point is adapted from source to destination (source white → destination white).

This is the correct default for virtually all display-to-display workflows: web images, app thumbnails, photo export, screen preview. Colors that fit in the destination gamut are reproduced without any remapping — what the numbers say is what you get.

Tradeoff: saturated gradients that cross the gamut boundary can show hard clipping artifacts (banding). If the source gamut is much wider than the destination (e.g., BT.2020 → sRGB), consider whether a perceptual-intent profile or a dedicated gamut-mapping step would produce smoother results.

§

Saturation

Maximize saturation and vividness, sacrificing hue accuracy. Designed for business graphics: charts, logos, presentation slides.

Not suitable for photographs. Hue shifts are expected and intentional — the goal is “vivid”, not “accurate”.

Like Perceptual, many profiles lack a saturation-intent LUT. When absent, the CMS falls back to the profile’s default intent.

§

AbsoluteColorimetric

Like RelativeColorimetric but without white point adaptation. Source white is preserved literally: a D50 (warm) source displayed on a D65 (cool) screen will show yellowish whites.

Use exclusively for soft-proofing: simulating how a print will look by preserving the paper white and ink gamut on screen. Never use for final output — the tinted whites look wrong on every display except the exact one being simulated.

Trait Implementations§

Source§

impl Clone for RenderingIntent

Source§

fn clone(&self) -> RenderingIntent

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for RenderingIntent

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for RenderingIntent

Source§

fn default() -> RenderingIntent

Returns the “default value” for a type. Read more
Source§

impl Hash for RenderingIntent

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for RenderingIntent

Source§

fn eq(&self, other: &RenderingIntent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for RenderingIntent

Source§

impl Eq for RenderingIntent

Source§

impl StructuralPartialEq for RenderingIntent

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.