Expand description

Traits for converting between color spaces.

Deriving

FromColorUnclamped can be derived in a mostly automatic way. The default minimum requirement is to implement FromColorUnclamped<Xyz>, but it can also be customized to make use of generics and have other manual implementations.

It is also recommended to derive or implement WithAlpha, to be able to convert between all Alpha wrapped color types.

Configuration Attributes

The derives can be configured using one or more #[palette(...)] attributes. They can be attached to either the item itself, or to the fields.

#[palette(
    component = "T",
    rgb_standard = "S",
    white_point = "<S::Space as RgbSpace>::WhitePoint",
)]
#[derive(FromColorUnclamped)]
#[repr(C)]
struct ExampleType<S: RgbStandard, T: Component> {
    // ...
    #[palette(alpha)]
    alpha: T,
    standard: std::marker::PhantomData<S>,
}

Item Attributes

  • skip_derives(Luma, Rgb): No conversion derives will be implemented for these colors. They are instead to be implemented manually, and serve as the basis for the automatic implementations.

  • white_point = "some::white_point::Type": Sets the white point type that should be used when deriving. The default is D65, but it may be any other type, including type parameters.

  • component = "some::component::Type": Sets the color component type that should be used when deriving. The default is f32, but it may be any other type, including type parameters.

  • rgb_standard = "some::rgb_standard::Type": Sets the RGB standard type that should be used when deriving. The default is to either use Srgb or a best effort to convert between standards, but sometimes it has to be set to a specific type. This also accepts type parameters.

Field Attributes

  • alpha: Specifies field as the color’s transparency value.

Examples

Minimum requirements implementation:

use palette::convert::FromColorUnclamped;
use palette::{Srgb, Xyz, IntoColor};

/// A custom version of Xyz that stores integer values from 0 to 100.
#[derive(PartialEq, Debug, FromColorUnclamped)]
struct Xyz100 {
    x: u8,
    y: u8,
    z: u8,
}

// We have to implement at least one "manual" conversion. The default
// is to and from `Xyz`, but it can be customized with `skip_derives(...)`.
impl FromColorUnclamped<Xyz> for Xyz100 {
    fn from_color_unclamped(color: Xyz) -> Xyz100 {
        Xyz100 {
            x: (color.x * 100.0) as u8,
            y: (color.y * 100.0) as u8,
            z: (color.z * 100.0) as u8,
        }
    }
}

impl FromColorUnclamped<Xyz100> for Xyz {
    fn from_color_unclamped(color: Xyz100) -> Xyz {
        Xyz::new(
            color.x as f32 / 100.0,
            color.y as f32 / 100.0,
            color.z as f32 / 100.0,
        )
    }
}

fn main() {
    // Start with an Xyz100 color.
    let xyz = Xyz100 {
        x: 59,
        y: 75,
        z: 42,
    };

    // Convert the color to sRGB.
    let rgb: Srgb = xyz.into_color();

    assert_eq!(rgb.into_format(), Srgb::new(196u8, 238, 154));
}

With generic components:

#[macro_use]
extern crate approx;

use palette::rgb::{Rgb, RgbSpace, RgbStandard};
use palette::encoding::Linear;
use palette::white_point::D65;
use palette::convert::{FromColorUnclamped, IntoColorUnclamped};
use palette::{FloatComponent, Hsv, Pixel, Srgb, IntoColor};

/// sRGB, but with a reversed memory layout.
#[palette(
    skip_derives(Rgb),
    component = "T",
    rgb_standard = "palette::encoding::Srgb"
)]
#[derive(Copy, Clone, Pixel, FromColorUnclamped)]
#[repr(C)] // Makes sure the memory layout is as we want it.
struct Bgr<T> {
    blue: T,
    green: T,
    red: T,
}

// It converts from and into any linear Rgb type that has the
// D65 white point, which is the default if we don't specify
// anything else with the `white_point` attribute argument.
impl<S, T> FromColorUnclamped<Bgr<T>> for Rgb<S, T>
where
    T: FloatComponent,
    S: RgbStandard,
    S::Space: RgbSpace<WhitePoint = D65>
{
    fn from_color_unclamped(color: Bgr<T>) -> Rgb<S, T> {
        Srgb::new(color.red, color.green, color.blue)
            .into_color_unclamped()
    }
}

impl<S, T> FromColorUnclamped<Rgb<S, T>> for Bgr<T>
where
    T: FloatComponent,
    S: RgbStandard,
    S::Space: RgbSpace<WhitePoint = D65>
{
    fn from_color_unclamped(color: Rgb<S, T>) -> Bgr<T> {
        let color = Srgb::from_color_unclamped(color);
        Bgr {
            blue: color.blue,
            green: color.green,
            red: color.red,
        }
    }
}

fn main() {
    let buffer = vec![
        0.0f64,
        0.0,
        0.0,
        0.0,
        0.5,
        0.25,
    ];
    let hsv: Hsv<_, f64> = Bgr::from_raw_slice(&buffer)[1].into_color();

    assert_relative_eq!(hsv, Hsv::new(90.0, 1.0, 0.5));
}

With alpha component:

#[macro_use]
extern crate approx;

use palette::{LinSrgba, Srgb, IntoColor, WithAlpha};
use palette::rgb::{Rgb, RgbSpace, RgbStandard};
use palette::encoding::Linear;
use palette::white_point::D65;
use palette::convert::{FromColorUnclamped, IntoColorUnclamped};

/// CSS style sRGB.
#[palette(
    skip_derives(Rgb),
    rgb_standard = "palette::encoding::Srgb"
)]
#[derive(PartialEq, Debug, FromColorUnclamped, WithAlpha)]
struct CssRgb {
    red: u8,
    green: u8,
    blue: u8,
    #[palette(alpha)]
    alpha: f32,
}

// We will write a conversion function for opaque RGB and
// `impl_default_conversions` will take care of preserving
// the transparency for us.
impl<S> FromColorUnclamped<Rgb<S, f32>> for CssRgb
where
    S: RgbStandard,
    S::Space: RgbSpace<WhitePoint = D65>,
{
    fn from_color_unclamped(color: Rgb<S, f32>) -> CssRgb{
        let srgb = Srgb::from_color_unclamped(color)
            .into_format();

        CssRgb {
            red: srgb.red,
            green: srgb.green,
            blue: srgb.blue,
            alpha: 1.0
        }
    }
}

impl<S> FromColorUnclamped<CssRgb> for Rgb<S, f32>
where
    S: RgbStandard,
    S::Space: RgbSpace<WhitePoint = D65>,
{
    fn from_color_unclamped(color: CssRgb) -> Rgb<S, f32>{
        Srgb::new(color.red, color.green, color.blue)
            .into_format()
            .into_color_unclamped()
    }
}

fn main() {
    let css_color = CssRgb {
        red: 187,
        green: 0,
        blue: 255,
        alpha: 0.3,
    };
    let color: LinSrgba = css_color.into_color();

    assert_relative_eq!(color, LinSrgba::new(0.496933, 0.0, 1.0, 0.3));
}

Structs

The error type for a color conversion that converted a color into a color with invalid values.

Traits

A trait for converting one color from another, in a possibly lossy way.

A trait for unchecked conversion of one color from another.

A trait for converting a color into another, in a possibly lossy way.

A trait for unchecked conversion of a color into another.

A trait for fallible conversion of one color from another.

A trait for fallible conversion of a color into another.