Skip to main content

ColorSpace

Enum ColorSpace 

Source
pub enum ColorSpace {
    Srgb,
    LinearSrgb,
    DisplayP3,
    LinearDisplayP3,
    Rec2020,
    LinearRec2020,
    Oklab,
    Oklch,
    Oklrab,
    Oklrch,
    Xyz,
    XyzD50,
}
Expand description

The enumeration of supported color spaces.

§RGB

This crate supports several RGB color spaces, each in its gamma-corrected and its linear form. From smallest to largest gamut, they are:

  • sRGB, which has long served as the default color space for the web.
  • Display P3, which is well-positioned to become sRGB’s successor.
  • Rec. 2020, which is the standard color space for ultra-high-definition (UDH) video and, when it comes to display hardware, currently aspirational.

For all three color spaces as well as all three linear versions, in-gamut coordinates range from 0 to 1, inclusive.

§The Oklab Variations

This crate supports the Oklab/Oklch and Oklrab/Oklrch color spaces. All four are variations of the same perceptually uniform color space, which, like CIELAB, uses one coordinate for lightness and two coordinates for “colorness.”

Oklab and Oklch reflect the original design. They improve on CIELAB by using the D65 standard illuminant (not the print-oriented D50), which is also used by sRGB and Display P3. They further improve on CIELAB by avoiding visible distortions around the blues. However, they also regress, as their lightness L is visibly biased towards dark tones. Oklrab and Oklrch, which were introduced nine months after Oklab/Oklch, feature a revised lightness Lr that closely resembles CIELAB’s uniform lightness.

Oklab/Oklrab use Cartesian coordinates a, b for colorness—with the a axis varying red/green and the b axis varying blue/yellow. Because they use Cartesian coordinates, computing color difference in Oklab/Oklrab is straight-forward: It simply is the Euclidian distance. In contrast, Oklch/Oklrch use polar coordinates C/h—with C expressing chroma and h or also hº expressing hue. That makes both color spaces well-suited to synthesizing and modifying colors.

Compared to the most other conversions between color spaces, conversions between the four Oklab variations are mathematically simpler and may not involve all coordinates. After all, there are four three-dimensional color spaces but only six distinct quantities:

Color spaceLightnessColorness 1Colorness 2
OklabLab
OklchLC
OklrabLrab
OklrchLrC

Valid coordinates observe the following invariants:

  • The (revised) lightness for all four color spaces is limited to 0..=1.
  • The a/b coordinates for Oklab/Oklrab have no set limits, but in practice can be bounded -0.4..=0.4.
  • The chroma for Oklch/Oklrch must be non-negative and in practice can be bounded 0..=0.4.
  • The hue for Oklch/Oklrch may be not-a-number, which indicates a powerless component, i.e., gray tone. In that case, the chroma must necessarily be zero.

Fundamentally, Oklab and Oklch are the same color space, only using different coordinate systems. Of course, that also is the case for Oklrab and Oklrch. The chroma bond corresponds to a circle with radius 0.4 that is centered at the origin. The a/b bounds correspond to a square with sides 0.8 that is also centered at the origin. The circle just fits into the square and covers an area of π×0.4². Meanwhile, the square covers an area of (2×0.4)², i.e., it is 4/π or 1.273 times larger. In other words, the a/b bounds are somewhat looser than the chroma bound.

There may or may not be another, still outstanding issue with Oklrab, namely that a and b need to be scaled by a factor of around 2.1.

There also is an extended Oklab, which behaves better for imaginary colors. As shown in the corresponding notebook, the implementation compresses and shifts the LMS coordinates during conversion.

§XYZ

XYZ serves as foundational color space. Notably, all conversions between unrelated color spaces go through XYZ. Since sRGB, Display P3, and Oklab use the D65 standard illuminant, this crate uses XYZ with D65 as its reference color space. But XYZ with the D50 standard illuminant is available, too. Chromatic adaptation between the two versions of XYZ uses the (linear) Bradford method.

Variants§

§

Srgb

§

LinearSrgb

§

DisplayP3

§

LinearDisplayP3

§

Rec2020

§

LinearRec2020

§

Oklab

§

Oklch

§

Oklrab

§

Oklrch

§

Xyz

§

XyzD50

Implementations§

Source§

impl ColorSpace

Source

pub const fn is_polar(&self) -> bool

Determine whether this color space is polar.

Oklch and Oklrch currently are the only polar color spaces.

Source

pub const fn is_xyz(&self) -> bool

Determine whether this color space is XYZ.

Source

pub const fn is_rgb(&self) -> bool

Determine whether this color space is RGB.

RGB color spaces are additive and have red, green, and blue coordinates. In-gamut colors have coordinates in unit range 0..=1.

Source

pub const fn is_ok(&self) -> bool

Determine whether this color space is one of the Oklab variations.

Source

pub const fn is_bounded(&self) -> bool

Determine whether this color space is bounded.

XYZ and the Oklab variations are unbounded and hence can model any color. By contrast, RGB color spaces are bounded, with coordinates of in-gamut colors ranging 0..=1.

Source

pub fn gamut(&self, edge_length: usize) -> Option<GamutTraversal>

Create an iterator over this color space’s gamut boundaries. Gamut only

For bounded or RGB color spaces, this method returns an iterator that traces the boundaries of the color space’s gamut. As described in detail for GamutTraversal, the iterator does so by yielding GamutTraversalSteps that trace paths along the edges of this color space’s RGB cube.

Altogether, the iterator yields steps for a closed path covering six edges followed by another six paths each covering one edge. Each step includes exactly one in-gamut color that also is in this color space. There are edge_length steps per edge, though the first path yields corners other than the blue primary only once.

If this color space is not bounded or the segment size is 0 or 1, this method returns None.

Trait Implementations§

Source§

impl Clone for ColorSpace

Source§

fn clone(&self) -> ColorSpace

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for ColorSpace

Source§

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

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

impl Display for ColorSpace

Source§

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

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

impl Hash for ColorSpace

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 ColorSpace

Source§

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

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · 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 ColorSpace

Source§

impl Eq for ColorSpace

Source§

impl StructuralPartialEq for ColorSpace

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> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. 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.