Trait palette::FromColor

source ·
pub trait FromColor<Wp = D65, T = f32>: Sized
where T: Component + Float, Wp: WhitePoint,
{ // Required method fn from_xyz(_: Xyz<Wp, T>) -> Self; // Provided methods fn from_yxy(inp: Yxy<Wp, T>) -> Self { ... } fn from_lab(inp: Lab<Wp, T>) -> Self { ... } fn from_lch(inp: Lch<Wp, T>) -> Self { ... } fn from_rgb<S: RgbSpace<WhitePoint = Wp>>(inp: Rgb<Linear<S>, T>) -> Self { ... } fn from_hsl<S: RgbSpace<WhitePoint = Wp>>(inp: Hsl<S, T>) -> Self { ... } fn from_hsv<S: RgbSpace<WhitePoint = Wp>>(inp: Hsv<S, T>) -> Self { ... } fn from_hwb<S: RgbSpace<WhitePoint = Wp>>(inp: Hwb<S, T>) -> Self { ... } fn from_luma(inp: Luma<Linear<Wp>, T>) -> Self { ... } }
Expand description

FromColor provides conversion from the colors.

It requires from_xyz, when implemented manually, and derives conversion to other colors as a default from this. These defaults must be overridden when direct conversion exists between colors. For example, Luma has direct conversion to LinRgb. So from_rgb conversion for Luma and from_luma for LinRgb is implemented directly. The from for the same color must override the default. For example, from_rgb for LinRgb will convert via Xyz which needs to be overridden with self to avoid the unnecessary conversion.

Deriving

FromColor can be derived in a mostly automatic way. The strength of deriving it is that it will also derive From implementations for all of the palette color types. The minimum requirement is to implement From<Xyz>, but it can also be customized to make use of generics and have other manual implementations.

Item Attributes

  • #[palette_manual_from(Luma, Rgb = "from_rgb_internal")]: Specifies the color types that the the custom color type already has From implementations for. Adding = "function_name" tells it to use that function instead of a From implementation. The default, when omitted, is to require From<Xyz> to be implemented.

  • #[palette_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.

  • #[palette_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.

  • #[palette_rgb_space = "some::rgb_space::Type"]: Sets the RGB space type that should be used when deriving. The default is to either use Srgb or a best effort to convert between spaces, so sometimes it has to be set to a specific type. This does also accept type parameters.

Field Attributes

  • #[palette_alpha]: Specifies that the field is the color’s transparency value.

Examples

Minimum requirements implementation:

#[macro_use]
extern crate palette;

use palette::{Srgb, Xyz};

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

// We have to at least implement conversion from Xyz if we don't
// specify anything else, using the `palette_manual_from` attribute.
impl From<Xyz> for Xyz100 {
    fn from(color: Xyz) -> Self {
        let scaled = color * 100.0;
        Xyz100 {
            x: scaled.x.max(0.0).min(100.0) as u8,
            y: scaled.y.max(0.0).min(100.0) as u8,
            z: scaled.z.max(0.0).min(100.0) as u8,
        }
    }
}

fn main() {
    // Start with an sRGB color and convert it from u8 to f32,
    // which is the default component type.
    let rgb = Srgb::new(196u8, 238, 155).into_format();

    // Convert the rgb color to our own format.
    let xyz = Xyz100::from(rgb);

    assert_eq!(
        xyz,
        Xyz100 {
            x: 59,
            y: 75,
            z: 42,
        }
    );
}

With generic components:

#[macro_use]
extern crate palette;
#[macro_use]
extern crate approx;

use palette::{Component, FromColor, Hsv, Pixel, Srgb};
use palette::rgb::{Rgb, RgbSpace};
use palette::encoding::Linear;
use palette::white_point::D65;
use palette::float::Float;

/// sRGB, but with a reversed memory layout.
#[derive(PartialEq, Debug, FromColor, Pixel)]
#[palette_manual_from(Rgb = "from_rgb_internal")]
#[palette_component = "T"]
#[repr(C)] // Makes sure the memory layout is as we want it.
struct Bgr<T> {
    blue: T,
    green: T,
    red: T,
}

// Rgb is a bit more complex than other colors, so we are
// implementing a private conversion function and letting it
// derive `From` automatically. It will take a round trip
// through linear format, but that's fine in this case.
impl<T: Component + Float> Bgr<T> {
    // It converts from any linear Rgb type that has the D65
    // white point, which is the default if we don't specify
    // anything else with the `palette_white_point` attribute.
    fn from_rgb_internal<S>(color: Rgb<Linear<S>, T>) -> Self
    where
        S: RgbSpace<WhitePoint = D65>,
    {
        let srgb = Srgb::from_rgb(color);

        Bgr {
            blue: srgb.blue,
            green: srgb.green,
            red: srgb.red,
        }
    }
}

fn main() {
    let mut buffer = vec![0.0f64, 0.0, 0.0, 0.0, 0.0, 0.0];
    {
        let bgr_buffer = Bgr::from_raw_slice_mut(&mut buffer);
        bgr_buffer[1] = Hsv::new(90.0, 1.0, 0.5).into();
    }

    assert_relative_eq!(buffer[3], 0.0);
    assert_relative_eq!(buffer[4], 0.7353569830524495);
    assert_relative_eq!(buffer[5], 0.5370987304831942);
}

With alpha component:

#[macro_use]
extern crate palette;

use palette::{FromColor, LinSrgba, Srgb};
use palette::rgb::{Rgb, RgbSpace};
use palette::encoding::Linear;
use palette::white_point::D65;

/// CSS style sRGB.
#[derive(PartialEq, Debug, FromColor)]
#[palette_manual_from(Rgb = "from_rgb_internal")]
struct CssRgb {
    red: u8,
    green: u8,
    blue: u8,
    #[palette_alpha]
    alpha: f32,
}

// We will write a conversion function for opaque RGB and derive
// will take care of preserving the transparency for us.
impl CssRgb {
    fn from_rgb_internal<S>(color: Rgb<Linear<S>, f32>) -> Self
    where
        S: RgbSpace<WhitePoint = D65>,
    {
        // Convert to u8 sRGB
        let srgb = Srgb::from_rgb(color).into_format();

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

fn main() {
    let color = LinSrgba::new(0.5, 0.0, 1.0, 0.3);
    let css_color = CssRgb::from(color);

    assert_eq!(
        css_color,
        CssRgb {
            red: 188,
            green: 0,
            blue: 255,
            alpha: 0.3,
        }
    );
}

Required Methods§

source

fn from_xyz(_: Xyz<Wp, T>) -> Self

Convert from XYZ color space

Provided Methods§

source

fn from_yxy(inp: Yxy<Wp, T>) -> Self

Convert from Yxy color space

source

fn from_lab(inp: Lab<Wp, T>) -> Self

Convert from L*a*b* color space

source

fn from_lch(inp: Lch<Wp, T>) -> Self

Convert from L*C*h° color space

source

fn from_rgb<S: RgbSpace<WhitePoint = Wp>>(inp: Rgb<Linear<S>, T>) -> Self

Convert from RGB color space

source

fn from_hsl<S: RgbSpace<WhitePoint = Wp>>(inp: Hsl<S, T>) -> Self

Convert from HSL color space

source

fn from_hsv<S: RgbSpace<WhitePoint = Wp>>(inp: Hsv<S, T>) -> Self

Convert from HSV color space

source

fn from_hwb<S: RgbSpace<WhitePoint = Wp>>(inp: Hwb<S, T>) -> Self

Convert from HWB color space

source

fn from_luma(inp: Luma<Linear<Wp>, T>) -> Self

Convert from Luma

Object Safety§

This trait is not object safe.

Implementors§

source§

impl<S, T> FromColor<<S as LumaStandard>::WhitePoint, T> for Luma<S, T>

source§

impl<S, T> FromColor<<S as RgbSpace>::WhitePoint, T> for Hsl<S, T>

source§

impl<S, T> FromColor<<S as RgbSpace>::WhitePoint, T> for Hsv<S, T>

source§

impl<S, T> FromColor<<S as RgbSpace>::WhitePoint, T> for Hwb<S, T>

source§

impl<S: RgbStandard, T> FromColor<<<S as RgbStandard>::Space as RgbSpace>::WhitePoint, T> for Rgb<S, T>

source§

impl<Wp, T> FromColor<Wp, T> for Lab<Wp, T>

source§

impl<Wp, T> FromColor<Wp, T> for Lch<Wp, T>

source§

impl<Wp, T> FromColor<Wp, T> for Xyz<Wp, T>

source§

impl<Wp, T> FromColor<Wp, T> for Yxy<Wp, T>