pub trait IntoColor<Wp = D65, T = f32>: Sized{
// Required method
fn into_xyz(self) -> Xyz<Wp, T>;
// Provided methods
fn into_yxy(self) -> Yxy<Wp, T> { ... }
fn into_lab(self) -> Lab<Wp, T> { ... }
fn into_lch(self) -> Lch<Wp, T> { ... }
fn into_rgb<S: RgbSpace<WhitePoint = Wp>>(self) -> Rgb<Linear<S>, T> { ... }
fn into_hsl<S: RgbSpace<WhitePoint = Wp>>(self) -> Hsl<S, T> { ... }
fn into_hsv<S: RgbSpace<WhitePoint = Wp>>(self) -> Hsv<S, T> { ... }
fn into_hwb<S: RgbSpace<WhitePoint = Wp>>(self) -> Hwb<S, T> { ... }
fn into_luma(self) -> Luma<Linear<Wp>, T> { ... }
}
Expand description
IntoColor provides conversion to the colors.
It requires into_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.
Deriving
IntoColor
can be derived in a mostly automatic way. The strength of deriving it is that it
will also derive Into
implementations for all of the palette
color types. The minimum
requirement is to implement Into<Xyz>
, but it can also be customized to make use of generics
and have other manual implementations.
Item Attributes
-
#[palette_manual_into(Luma, Rgb = "into_rgb_internal")]
: Specifies the color types that the the custom color type already hasInto
implementations for. Adding= "function_name"
tells it to use that function instead of anInto
implementation. The default, when omitted, is to requireInto<Xyz>
to be implemented. -
#[palette_white_point = "some::white_point::Type"]
: Sets the white point type that should be used when deriving. The default isD65
, 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 isf32
, 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 useSrgb
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, IntoColor)]
struct Xyz100 {
x: u8,
y: u8,
z: u8,
}
// We have to at least implement conversion into Xyz if we don't
// specify anything else, using the `palette_manual_into` attribute.
impl Into<Xyz> for Xyz100 {
fn into(self) -> Xyz {
Xyz::new(
self.x as f32 / 100.0,
self.y as f32 / 100.0,
self.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();
assert_eq!(rgb.into_format(), Srgb::new(196u8, 238, 154));
}
With generic components:
#[macro_use]
extern crate palette;
#[macro_use]
extern crate approx;
use palette::{Component, Hsv, IntoColor, Pixel, Srgb};
use palette::rgb::{Rgb, RgbSpace};
use palette::encoding::{Linear, self};
use palette::white_point::D65;
use palette::float::Float;
type Hsv64 = Hsv<encoding::Srgb, f64>;
/// sRGB, but with a reversed memory layout.
#[derive(Copy, Clone, IntoColor, Pixel)]
#[palette_manual_into(Rgb = "into_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 `Into` automatically.
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 into_rgb_internal<S>(self) -> Rgb<Linear<S>, T>
where
S: RgbSpace<WhitePoint = D65>,
{
Srgb::new(self.red, self.green, self.blue).into_rgb()
}
}
fn main() {
let buffer = vec![
0.0f64,
0.0,
0.0,
0.0,
0.7353569830524495,
0.5370987304831942,
];
let hsv: Hsv64 = Bgr::from_raw_slice(&buffer)[1].into();
assert_relative_eq!(hsv, Hsv::new(90.0, 1.0, 0.5));
}
With alpha component:
#[macro_use]
extern crate palette;
#[macro_use]
extern crate approx;
use palette::{IntoColor, LinSrgba, Srgb};
use palette::rgb::{Rgb, RgbSpace};
use palette::encoding::Linear;
use palette::white_point::D65;
/// CSS style sRGB.
#[derive(PartialEq, Debug, IntoColor)]
#[palette_manual_into(Rgb = "into_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 into_rgb_internal<S>(self) -> Rgb<Linear<S>, f32>
where
S: RgbSpace<WhitePoint = D65>,
{
Srgb::new(self.red, self.green, self.blue)
.into_format()
.into_rgb()
}
}
fn main() {
let css_color = CssRgb {
red: 187,
green: 0,
blue: 255,
alpha: 0.3,
};
let color: LinSrgba = css_color.into();
assert_relative_eq!(color, LinSrgba::new(0.496933, 0.0, 1.0, 0.3));
}