mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 12:43:34 +00:00
bevy_color
: Added Xyza
Colour Space (#12079)
# Objective Add XYZ colour space. This will be most useful as a conversion step when working with other (more common) colour spaces. See [Wikipedia](https://en.wikipedia.org/wiki/CIE_1931_color_space) for details on this space. ## Solution - Added `Xyza` to `Color` and as its own type. --- ## Changelog - Added `Xyza` type. - Added `Color::Xyza` variant. ## Migration Guide - `Color` enum now has an additional member, `Xyza`. Convert it to any other type to handle this case in match statements.
This commit is contained in:
parent
65267dd1f9
commit
972ca62831
5 changed files with 312 additions and 4 deletions
|
@ -1,4 +1,4 @@
|
|||
use palette::{Hsl, IntoColor, Lch, LinSrgb, Oklab, Srgb};
|
||||
use palette::{Hsl, IntoColor, Lch, LinSrgb, Oklab, Srgb, Xyz};
|
||||
|
||||
const TEST_COLORS: &[(f32, f32, f32, &str)] = &[
|
||||
(0., 0., 0., "black"),
|
||||
|
@ -25,7 +25,7 @@ fn main() {
|
|||
println!(
|
||||
"// Generated by gen_tests. Do not edit.
|
||||
#[cfg(test)]
|
||||
use crate::{{Hsla, Srgba, LinearRgba, Oklaba, Lcha}};
|
||||
use crate::{{Hsla, Srgba, LinearRgba, Oklaba, Lcha, Xyza}};
|
||||
|
||||
#[cfg(test)]
|
||||
pub struct TestColor {{
|
||||
|
@ -35,6 +35,7 @@ pub struct TestColor {{
|
|||
pub hsl: Hsla,
|
||||
pub lch: Lcha,
|
||||
pub oklab: Oklaba,
|
||||
pub xyz: Xyza,
|
||||
}}
|
||||
"
|
||||
);
|
||||
|
@ -48,6 +49,7 @@ pub struct TestColor {{
|
|||
let hsl: Hsl = srgb.into_color();
|
||||
let lch: Lch = srgb.into_color();
|
||||
let oklab: Oklab = srgb.into_color();
|
||||
let xyz: Xyz = srgb.into_color();
|
||||
println!(" // {name}");
|
||||
println!(
|
||||
" TestColor {{
|
||||
|
@ -57,6 +59,7 @@ pub struct TestColor {{
|
|||
hsl: Hsla::new({}, {}, {}, 1.0),
|
||||
lch: Lcha::new({}, {}, {}, 1.0),
|
||||
oklab: Oklaba::new({}, {}, {}, 1.0),
|
||||
xyz: Xyza::new({}, {}, {}, 1.0),
|
||||
}},",
|
||||
VariablePrecision(srgb.red),
|
||||
VariablePrecision(srgb.green),
|
||||
|
@ -73,6 +76,9 @@ pub struct TestColor {{
|
|||
VariablePrecision(oklab.l),
|
||||
VariablePrecision(oklab.a),
|
||||
VariablePrecision(oklab.b),
|
||||
VariablePrecision(xyz.x),
|
||||
VariablePrecision(xyz.y),
|
||||
VariablePrecision(xyz.z),
|
||||
);
|
||||
}
|
||||
println!("];");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Alpha, Hsla, Lcha, LinearRgba, Oklaba, Srgba, StandardColor};
|
||||
use crate::{Alpha, Hsla, Lcha, LinearRgba, Oklaba, Srgba, StandardColor, Xyza};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_render::color::Color as LegacyColor;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -20,6 +20,8 @@ pub enum Color {
|
|||
Lcha(Lcha),
|
||||
/// A color in the Oklaba color space with alpha.
|
||||
Oklaba(Oklaba),
|
||||
/// A color in the XYZ color space with alpha.
|
||||
Xyza(Xyza),
|
||||
}
|
||||
|
||||
impl StandardColor for Color {}
|
||||
|
@ -33,6 +35,7 @@ impl Color {
|
|||
Color::Hsla(hsla) => (*hsla).into(),
|
||||
Color::Lcha(lcha) => (*lcha).into(),
|
||||
Color::Oklaba(oklab) => (*oklab).into(),
|
||||
Color::Xyza(xyza) => (*xyza).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -53,6 +56,7 @@ impl Alpha for Color {
|
|||
Color::Hsla(x) => *x = x.with_alpha(alpha),
|
||||
Color::Lcha(x) => *x = x.with_alpha(alpha),
|
||||
Color::Oklaba(x) => *x = x.with_alpha(alpha),
|
||||
Color::Xyza(x) => *x = x.with_alpha(alpha),
|
||||
}
|
||||
|
||||
new
|
||||
|
@ -65,6 +69,7 @@ impl Alpha for Color {
|
|||
Color::Hsla(x) => x.alpha(),
|
||||
Color::Lcha(x) => x.alpha(),
|
||||
Color::Oklaba(x) => x.alpha(),
|
||||
Color::Xyza(x) => x.alpha(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -99,6 +104,12 @@ impl From<Lcha> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Color {
|
||||
fn from(value: Xyza) -> Self {
|
||||
Self::Xyza(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Srgba {
|
||||
fn from(value: Color) -> Self {
|
||||
match value {
|
||||
|
@ -107,6 +118,7 @@ impl From<Color> for Srgba {
|
|||
Color::Hsla(hsla) => hsla.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +131,7 @@ impl From<Color> for LinearRgba {
|
|||
Color::Hsla(hsla) => hsla.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +144,7 @@ impl From<Color> for Hsla {
|
|||
Color::Hsla(hsla) => hsla,
|
||||
Color::Lcha(lcha) => LinearRgba::from(lcha).into(),
|
||||
Color::Oklaba(oklab) => LinearRgba::from(oklab).into(),
|
||||
Color::Xyza(xyza) => LinearRgba::from(xyza).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,6 +157,7 @@ impl From<Color> for Lcha {
|
|||
Color::Hsla(hsla) => Srgba::from(hsla).into(),
|
||||
Color::Lcha(lcha) => lcha,
|
||||
Color::Oklaba(oklab) => LinearRgba::from(oklab).into(),
|
||||
Color::Xyza(xyza) => LinearRgba::from(xyza).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +170,20 @@ impl From<Color> for Oklaba {
|
|||
Color::Hsla(hsla) => Srgba::from(hsla).into(),
|
||||
Color::Lcha(lcha) => LinearRgba::from(lcha).into(),
|
||||
Color::Oklaba(oklab) => oklab,
|
||||
Color::Xyza(xyza) => LinearRgba::from(xyza).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Xyza {
|
||||
fn from(value: Color) -> Self {
|
||||
match value {
|
||||
Color::Srgba(x) => x.into(),
|
||||
Color::LinearRgba(x) => x.into(),
|
||||
Color::Hsla(x) => x.into(),
|
||||
Color::Lcha(x) => x.into(),
|
||||
Color::Oklaba(x) => x.into(),
|
||||
Color::Xyza(xyza) => xyza,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -178,6 +207,7 @@ impl From<Color> for LegacyColor {
|
|||
Color::Hsla(x) => x.into(),
|
||||
Color::Lcha(x) => x.into(),
|
||||
Color::Oklaba(x) => x.into(),
|
||||
Color::Xyza(x) => x.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
//! - [`Hsla`] (hue, saturation, lightness, alpha)
|
||||
//! - [`Lcha`] (lightness, chroma, hue, alpha)
|
||||
//! - [`Oklaba`] (lightness, a-axis, b-axis, alpha)
|
||||
//! - [`Xyza`] (x-axis, y-axis, z-axis, alpha)
|
||||
//!
|
||||
//! Each of these color spaces is represented as a distinct Rust type.
|
||||
//!
|
||||
|
@ -35,6 +36,10 @@
|
|||
//! for tasks such as color correction and image analysis, where it is important to be able
|
||||
//! to do things like change color saturation without causing hue shifts.
|
||||
//!
|
||||
//! XYZ is a foundational space commonly used in the definition of other more modern color
|
||||
//! spaces. The space is more formally known as CIE 1931, where the `x` and `z` axes represent
|
||||
//! a form of chromaticity, while `y` defines an illuminance level.
|
||||
//!
|
||||
//! See also the [Wikipedia article on color spaces](https://en.wikipedia.org/wiki/Color_space).
|
||||
//!
|
||||
//! # Conversions
|
||||
|
@ -78,6 +83,7 @@ mod srgba;
|
|||
mod test_colors;
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
mod xyza;
|
||||
|
||||
pub use color::*;
|
||||
pub use color_ops::*;
|
||||
|
@ -87,6 +93,7 @@ pub use lcha::*;
|
|||
pub use linear_rgba::*;
|
||||
pub use oklaba::*;
|
||||
pub use srgba::*;
|
||||
pub use xyza::*;
|
||||
|
||||
use bevy_render::color::Color as LegacyColor;
|
||||
|
||||
|
@ -106,6 +113,7 @@ where
|
|||
Self: From<Hsla> + Into<Hsla>,
|
||||
Self: From<Lcha> + Into<Lcha>,
|
||||
Self: From<Oklaba> + Into<Oklaba>,
|
||||
Self: From<Xyza> + Into<Xyza>,
|
||||
Self: Alpha,
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Generated by gen_tests. Do not edit.
|
||||
#[cfg(test)]
|
||||
use crate::{Hsla, Lcha, LinearRgba, Oklaba, Srgba};
|
||||
use crate::{Hsla, Lcha, LinearRgba, Oklaba, Srgba, Xyza};
|
||||
|
||||
#[cfg(test)]
|
||||
pub struct TestColor {
|
||||
|
@ -10,6 +10,7 @@ pub struct TestColor {
|
|||
pub hsl: Hsla,
|
||||
pub lch: Lcha,
|
||||
pub oklab: Oklaba,
|
||||
pub xyz: Xyza,
|
||||
}
|
||||
|
||||
// Table of equivalent colors in various color spaces
|
||||
|
@ -23,6 +24,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(0.0, 0.0, 0.0, 1.0),
|
||||
lch: Lcha::new(0.0, 0.0, 0.0000136603785, 1.0),
|
||||
oklab: Oklaba::new(0.0, 0.0, 0.0, 1.0),
|
||||
xyz: Xyza::new(0.0, 0.0, 0.0, 1.0),
|
||||
},
|
||||
// white
|
||||
TestColor {
|
||||
|
@ -32,6 +34,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(0.0, 0.0, 1.0, 1.0),
|
||||
lch: Lcha::new(1.0, 0.0, 0.0000136603785, 1.0),
|
||||
oklab: Oklaba::new(1.0, 0.0, 0.000000059604645, 1.0),
|
||||
xyz: Xyza::new(0.95047, 1.0, 1.08883, 1.0),
|
||||
},
|
||||
// red
|
||||
TestColor {
|
||||
|
@ -41,6 +44,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(0.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.53240794, 1.0455177, 39.99901, 1.0),
|
||||
oklab: Oklaba::new(0.6279554, 0.22486295, 0.1258463, 1.0),
|
||||
xyz: Xyza::new(0.4124564, 0.2126729, 0.0193339, 1.0),
|
||||
},
|
||||
// green
|
||||
TestColor {
|
||||
|
@ -50,6 +54,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(120.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.87734723, 1.1977587, 136.01595, 1.0),
|
||||
oklab: Oklaba::new(0.8664396, -0.2338874, 0.1794985, 1.0),
|
||||
xyz: Xyza::new(0.3575761, 0.7151522, 0.119192, 1.0),
|
||||
},
|
||||
// blue
|
||||
TestColor {
|
||||
|
@ -59,6 +64,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(240.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.32297012, 1.3380761, 306.28494, 1.0),
|
||||
oklab: Oklaba::new(0.4520137, -0.032456964, -0.31152815, 1.0),
|
||||
xyz: Xyza::new(0.1804375, 0.072175, 0.9503041, 1.0),
|
||||
},
|
||||
// yellow
|
||||
TestColor {
|
||||
|
@ -68,6 +74,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(60.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.9713927, 0.96905375, 102.85126, 1.0),
|
||||
oklab: Oklaba::new(0.9679827, -0.07136908, 0.19856972, 1.0),
|
||||
xyz: Xyza::new(0.7700325, 0.9278251, 0.1385259, 1.0),
|
||||
},
|
||||
// magenta
|
||||
TestColor {
|
||||
|
@ -77,6 +84,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(300.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.6032421, 1.1554068, 328.23495, 1.0),
|
||||
oklab: Oklaba::new(0.7016738, 0.27456632, -0.16915613, 1.0),
|
||||
xyz: Xyza::new(0.5928939, 0.28484792, 0.969638, 1.0),
|
||||
},
|
||||
// cyan
|
||||
TestColor {
|
||||
|
@ -86,6 +94,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(180.0, 1.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.9111322, 0.50120866, 196.37614, 1.0),
|
||||
oklab: Oklaba::new(0.90539926, -0.1494439, -0.039398134, 1.0),
|
||||
xyz: Xyza::new(0.5380136, 0.78732723, 1.069496, 1.0),
|
||||
},
|
||||
// gray
|
||||
TestColor {
|
||||
|
@ -95,6 +104,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(0.0, 0.0, 0.5, 1.0),
|
||||
lch: Lcha::new(0.5338897, 0.00000011920929, 90.0, 1.0),
|
||||
oklab: Oklaba::new(0.5981807, 0.00000011920929, 0.0, 1.0),
|
||||
xyz: Xyza::new(0.2034397, 0.21404117, 0.23305441, 1.0),
|
||||
},
|
||||
// olive
|
||||
TestColor {
|
||||
|
@ -104,6 +114,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(60.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.51677734, 0.57966936, 102.851265, 1.0),
|
||||
oklab: Oklaba::new(0.57902855, -0.042691574, 0.11878061, 1.0),
|
||||
xyz: Xyza::new(0.16481864, 0.19859275, 0.029650241, 1.0),
|
||||
},
|
||||
// purple
|
||||
TestColor {
|
||||
|
@ -113,6 +124,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(300.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.29655674, 0.69114214, 328.23495, 1.0),
|
||||
oklab: Oklaba::new(0.41972777, 0.1642403, -0.10118592, 1.0),
|
||||
xyz: Xyza::new(0.12690368, 0.060969174, 0.20754242, 1.0),
|
||||
},
|
||||
// teal
|
||||
TestColor {
|
||||
|
@ -122,6 +134,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(180.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.48073065, 0.29981336, 196.37614, 1.0),
|
||||
oklab: Oklaba::new(0.54159236, -0.08939436, -0.02356726, 1.0),
|
||||
xyz: Xyza::new(0.11515705, 0.16852042, 0.22891617, 1.0),
|
||||
},
|
||||
// maroon
|
||||
TestColor {
|
||||
|
@ -131,6 +144,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(0.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.2541851, 0.61091745, 38.350803, 1.0),
|
||||
oklab: Oklaba::new(0.3756308, 0.13450874, 0.07527886, 1.0),
|
||||
xyz: Xyza::new(0.08828264, 0.045520753, 0.0041382504, 1.0),
|
||||
},
|
||||
// lime
|
||||
TestColor {
|
||||
|
@ -140,6 +154,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(120.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.46052113, 0.71647626, 136.01596, 1.0),
|
||||
oklab: Oklaba::new(0.5182875, -0.13990697, 0.10737252, 1.0),
|
||||
xyz: Xyza::new(0.076536, 0.153072, 0.025511991, 1.0),
|
||||
},
|
||||
// navy
|
||||
TestColor {
|
||||
|
@ -149,6 +164,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(240.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.12890343, 0.8004114, 306.28494, 1.0),
|
||||
oklab: Oklaba::new(0.27038592, -0.01941514, -0.18635012, 1.0),
|
||||
xyz: Xyza::new(0.03862105, 0.01544842, 0.20340417, 1.0),
|
||||
},
|
||||
// orange
|
||||
TestColor {
|
||||
|
@ -158,6 +174,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(60.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.51677734, 0.57966936, 102.851265, 1.0),
|
||||
oklab: Oklaba::new(0.57902855, -0.042691574, 0.11878061, 1.0),
|
||||
xyz: Xyza::new(0.16481864, 0.19859275, 0.029650241, 1.0),
|
||||
},
|
||||
// fuchsia
|
||||
TestColor {
|
||||
|
@ -167,6 +184,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(300.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.29655674, 0.69114214, 328.23495, 1.0),
|
||||
oklab: Oklaba::new(0.41972777, 0.1642403, -0.10118592, 1.0),
|
||||
xyz: Xyza::new(0.12690368, 0.060969174, 0.20754242, 1.0),
|
||||
},
|
||||
// aqua
|
||||
TestColor {
|
||||
|
@ -176,5 +194,6 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsl: Hsla::new(180.0, 1.0, 0.25, 1.0),
|
||||
lch: Lcha::new(0.48073065, 0.29981336, 196.37614, 1.0),
|
||||
oklab: Oklaba::new(0.54159236, -0.08939436, -0.02356726, 1.0),
|
||||
xyz: Xyza::new(0.11515705, 0.16852042, 0.22891617, 1.0),
|
||||
},
|
||||
];
|
||||
|
|
245
crates/bevy_color/src/xyza.rs
Normal file
245
crates/bevy_color/src/xyza.rs
Normal file
|
@ -0,0 +1,245 @@
|
|||
use crate::{Alpha, Hsla, Lcha, LinearRgba, Luminance, Mix, Oklaba, Srgba, StandardColor};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use bevy_render::color::Color;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// [CIE 1931](https://en.wikipedia.org/wiki/CIE_1931_color_space) color space, also known as XYZ, with an alpha channel.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
|
||||
#[reflect(PartialEq, Serialize, Deserialize)]
|
||||
pub struct Xyza {
|
||||
/// The x-axis. [0.0, 1.0]
|
||||
pub x: f32,
|
||||
/// The y-axis, intended to represent luminance. [0.0, 1.0]
|
||||
pub y: f32,
|
||||
/// The z-axis. [0.0, 1.0]
|
||||
pub z: f32,
|
||||
/// The alpha channel. [0.0, 1.0]
|
||||
pub alpha: f32,
|
||||
}
|
||||
|
||||
impl StandardColor for Xyza {}
|
||||
|
||||
impl Xyza {
|
||||
/// Construct a new [`Xyza`] color from components.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `x` - x-axis. [0.0, 1.0]
|
||||
/// * `y` - y-axis. [0.0, 1.0]
|
||||
/// * `z` - z-axis. [0.0, 1.0]
|
||||
/// * `alpha` - Alpha channel. [0.0, 1.0]
|
||||
pub const fn new(x: f32, y: f32, z: f32, alpha: f32) -> Self {
|
||||
Self { x, y, z, alpha }
|
||||
}
|
||||
|
||||
/// Construct a new [`Xyza`] color from (x, y, z) components, with the default alpha (1.0).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `x` - x-axis. [0.0, 1.0]
|
||||
/// * `y` - y-axis. [0.0, 1.0]
|
||||
/// * `z` - z-axis. [0.0, 1.0]
|
||||
pub const fn rgb(x: f32, y: f32, z: f32) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
alpha: 1.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Xyza {
|
||||
fn default() -> Self {
|
||||
Self::new(0., 0., 0., 1.)
|
||||
}
|
||||
}
|
||||
|
||||
impl Alpha for Xyza {
|
||||
#[inline]
|
||||
fn with_alpha(&self, alpha: f32) -> Self {
|
||||
Self { alpha, ..*self }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alpha(&self) -> f32 {
|
||||
self.alpha
|
||||
}
|
||||
}
|
||||
|
||||
impl Luminance for Xyza {
|
||||
#[inline]
|
||||
fn with_luminance(&self, lightness: f32) -> Self {
|
||||
Self {
|
||||
y: lightness,
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
fn luminance(&self) -> f32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
fn darker(&self, amount: f32) -> Self {
|
||||
Self {
|
||||
y: (self.y - amount).clamp(0., 1.),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
|
||||
fn lighter(&self, amount: f32) -> Self {
|
||||
Self {
|
||||
y: (self.y + amount).min(1.),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mix for Xyza {
|
||||
#[inline]
|
||||
fn mix(&self, other: &Self, factor: f32) -> Self {
|
||||
let n_factor = 1.0 - factor;
|
||||
Self {
|
||||
x: self.x * n_factor + other.x * factor,
|
||||
y: self.y * n_factor + other.y * factor,
|
||||
z: self.z * n_factor + other.z * factor,
|
||||
alpha: self.alpha * n_factor + other.alpha * factor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LinearRgba> for Xyza {
|
||||
fn from(
|
||||
LinearRgba {
|
||||
red,
|
||||
green,
|
||||
blue,
|
||||
alpha,
|
||||
}: LinearRgba,
|
||||
) -> Self {
|
||||
// Linear sRGB to XYZ
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html (sRGB, RGB to XYZ [M])
|
||||
let r = red;
|
||||
let g = green;
|
||||
let b = blue;
|
||||
|
||||
let x = r * 0.4124564 + g * 0.3575761 + b * 0.1804375;
|
||||
let y = r * 0.2126729 + g * 0.7151522 + b * 0.072175;
|
||||
let z = r * 0.0193339 + g * 0.119192 + b * 0.9503041;
|
||||
|
||||
Xyza::new(x, y, z, alpha)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for LinearRgba {
|
||||
fn from(Xyza { x, y, z, alpha }: Xyza) -> Self {
|
||||
// XYZ to Linear sRGB
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_RGB.html
|
||||
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html (sRGB, XYZ to RGB [M]-1)
|
||||
let r = x * 3.2404542 + y * -1.5371385 + z * -0.4985314;
|
||||
let g = x * -0.969266 + y * 1.8760108 + z * 0.041556;
|
||||
let b = x * 0.0556434 + y * -0.2040259 + z * 1.0572252;
|
||||
|
||||
LinearRgba::new(r, g, b, alpha)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Srgba> for Xyza {
|
||||
fn from(value: Srgba) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Srgba {
|
||||
fn from(value: Xyza) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Hsla> for Xyza {
|
||||
fn from(value: Hsla) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Hsla {
|
||||
fn from(value: Xyza) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Lcha> for Xyza {
|
||||
fn from(value: Lcha) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Lcha {
|
||||
fn from(value: Xyza) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklaba> for Xyza {
|
||||
fn from(value: Oklaba) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Oklaba {
|
||||
fn from(value: Xyza) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Xyza {
|
||||
fn from(value: Color) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Color {
|
||||
fn from(value: Xyza) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
color_difference::EuclideanDistance, test_colors::TEST_COLORS, testing::assert_approx_eq,
|
||||
Srgba,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_to_from_srgba() {
|
||||
let xyza = Xyza::new(0.5, 0.5, 0.5, 1.0);
|
||||
let srgba: Srgba = xyza.into();
|
||||
let xyza2: Xyza = srgba.into();
|
||||
assert_approx_eq!(xyza.x, xyza2.x, 0.001);
|
||||
assert_approx_eq!(xyza.y, xyza2.y, 0.001);
|
||||
assert_approx_eq!(xyza.z, xyza2.z, 0.001);
|
||||
assert_approx_eq!(xyza.alpha, xyza2.alpha, 0.001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_from_srgba_2() {
|
||||
for color in TEST_COLORS.iter() {
|
||||
let rgb2: Srgba = (color.xyz).into();
|
||||
let xyz2: Xyza = (color.rgb).into();
|
||||
assert!(
|
||||
color.rgb.distance(&rgb2) < 0.00001,
|
||||
"{}: {:?} != {:?}",
|
||||
color.name,
|
||||
color.rgb,
|
||||
rgb2
|
||||
);
|
||||
assert_approx_eq!(color.xyz.x, xyz2.x, 0.001);
|
||||
assert_approx_eq!(color.xyz.y, xyz2.y, 0.001);
|
||||
assert_approx_eq!(color.xyz.z, xyz2.z, 0.001);
|
||||
assert_approx_eq!(color.xyz.alpha, xyz2.alpha, 0.001);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue