mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
bevy_color
: Add Oklch Color Space (#12168)
# Objective - Complete compatibility with CSS Module 4 ## Solution - Added `Oklcha` which implements the Oklch color model. - Updated `Color` and `LegacyColor` accordingly. ## Migration Guide - Convert `Oklcha` to `Oklaba` using the provided `From` implementations and then handle accordingly. ## Notes This is the _last_ color space missing from the CSS Module 4 standard, and is also the one I believe we should recommend users actually work with for hand-crafting colours. It has all the uniformity benefits of Oklab combined with the intuition chroma and hue provide (when compared to a-axis and b-axis parameters).
This commit is contained in:
parent
6f849d32c8
commit
6774e042c7
6 changed files with 425 additions and 7 deletions
|
@ -1,4 +1,4 @@
|
|||
use palette::{Hsl, Hsv, Hwb, IntoColor, Lab, Lch, LinSrgb, Oklab, Srgb, Xyz};
|
||||
use palette::{Hsl, Hsv, Hwb, IntoColor, Lab, Lch, LinSrgb, Oklab, Oklch, 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, Hsva, Hwba, Srgba, LinearRgba, Oklaba, Laba, Lcha, Xyza}};
|
||||
use crate::{{Hsla, Hsva, Hwba, Srgba, LinearRgba, Oklaba, Oklcha, Laba, Lcha, Xyza}};
|
||||
|
||||
#[cfg(test)]
|
||||
pub struct TestColor {{
|
||||
|
@ -38,6 +38,7 @@ pub struct TestColor {{
|
|||
pub lab: Laba,
|
||||
pub lch: Lcha,
|
||||
pub oklab: Oklaba,
|
||||
pub oklch: Oklcha,
|
||||
pub xyz: Xyza,
|
||||
}}
|
||||
"
|
||||
|
@ -55,6 +56,7 @@ pub struct TestColor {{
|
|||
let lab: Lab = srgb.into_color();
|
||||
let lch: Lch = srgb.into_color();
|
||||
let oklab: Oklab = srgb.into_color();
|
||||
let oklch: Oklch = srgb.into_color();
|
||||
let xyz: Xyz = srgb.into_color();
|
||||
println!(" // {name}");
|
||||
println!(
|
||||
|
@ -68,6 +70,7 @@ pub struct TestColor {{
|
|||
lab: Laba::new({}, {}, {}, 1.0),
|
||||
lch: Lcha::new({}, {}, {}, 1.0),
|
||||
oklab: Oklaba::new({}, {}, {}, 1.0),
|
||||
oklch: Oklcha::new({}, {}, {}, 1.0),
|
||||
xyz: Xyza::new({}, {}, {}, 1.0),
|
||||
}},",
|
||||
VariablePrecision(srgb.red),
|
||||
|
@ -94,6 +97,9 @@ pub struct TestColor {{
|
|||
VariablePrecision(oklab.l),
|
||||
VariablePrecision(oklab.a),
|
||||
VariablePrecision(oklab.b),
|
||||
VariablePrecision(oklch.l),
|
||||
VariablePrecision(oklch.chroma),
|
||||
VariablePrecision(oklch.hue.into_positive_degrees()),
|
||||
VariablePrecision(xyz.x),
|
||||
VariablePrecision(xyz.y),
|
||||
VariablePrecision(xyz.z),
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
use crate::{Alpha, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Srgba, StandardColor, Xyza};
|
||||
use crate::{
|
||||
Alpha, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Srgba, StandardColor, Xyza,
|
||||
};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -29,6 +31,8 @@ pub enum Color {
|
|||
Lcha(Lcha),
|
||||
/// A color in the Oklaba color space with alpha.
|
||||
Oklaba(Oklaba),
|
||||
/// A color in the Oklcha color space with alpha.
|
||||
Oklcha(Oklcha),
|
||||
/// A color in the XYZ color space with alpha.
|
||||
Xyza(Xyza),
|
||||
}
|
||||
|
@ -196,6 +200,26 @@ impl Color {
|
|||
})
|
||||
}
|
||||
|
||||
/// Creates a new [`Color`] object storing a [`Oklcha`] color.
|
||||
pub const fn oklcha(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
|
||||
Self::Oklcha(Oklcha {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
alpha,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new [`Color`] object storing a [`Oklcha`] color with an alpha of 1.0.
|
||||
pub const fn oklch(lightness: f32, chroma: f32, hue: f32) -> Self {
|
||||
Self::Oklcha(Oklcha {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
alpha: 1.0,
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new [`Color`] object storing a [`Xyza`] color.
|
||||
pub const fn xyza(x: f32, y: f32, z: f32, alpha: f32) -> Self {
|
||||
Self::Xyza(Xyza { x, y, z, alpha })
|
||||
|
@ -241,6 +265,7 @@ impl Alpha for Color {
|
|||
Color::Laba(x) => *x = x.with_alpha(alpha),
|
||||
Color::Lcha(x) => *x = x.with_alpha(alpha),
|
||||
Color::Oklaba(x) => *x = x.with_alpha(alpha),
|
||||
Color::Oklcha(x) => *x = x.with_alpha(alpha),
|
||||
Color::Xyza(x) => *x = x.with_alpha(alpha),
|
||||
}
|
||||
|
||||
|
@ -257,6 +282,7 @@ impl Alpha for Color {
|
|||
Color::Laba(x) => x.alpha(),
|
||||
Color::Lcha(x) => x.alpha(),
|
||||
Color::Oklaba(x) => x.alpha(),
|
||||
Color::Oklcha(x) => x.alpha(),
|
||||
Color::Xyza(x) => x.alpha(),
|
||||
}
|
||||
}
|
||||
|
@ -298,6 +324,12 @@ impl From<Oklaba> for Color {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Color {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Self::Oklcha(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Lcha> for Color {
|
||||
fn from(value: Lcha) -> Self {
|
||||
Self::Lcha(value)
|
||||
|
@ -327,6 +359,7 @@ impl From<Color> for Srgba {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -343,6 +376,7 @@ impl From<Color> for LinearRgba {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -359,6 +393,7 @@ impl From<Color> for Hsla {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -375,6 +410,7 @@ impl From<Color> for Hsva {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -391,6 +427,7 @@ impl From<Color> for Hwba {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -407,6 +444,7 @@ impl From<Color> for Laba {
|
|||
Color::Laba(laba) => laba,
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -423,6 +461,7 @@ impl From<Color> for Lcha {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha,
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -439,6 +478,24 @@ impl From<Color> for Oklaba {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab,
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for Oklcha {
|
||||
fn from(value: Color) -> Self {
|
||||
match value {
|
||||
Color::Srgba(srgba) => srgba.into(),
|
||||
Color::LinearRgba(linear) => linear.into(),
|
||||
Color::Hsla(hsla) => hsla.into(),
|
||||
Color::Hsva(hsva) => hsva.into(),
|
||||
Color::Hwba(hwba) => hwba.into(),
|
||||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(lcha) => lcha.into(),
|
||||
Color::Oklaba(oklab) => oklab.into(),
|
||||
Color::Oklcha(oklch) => oklch,
|
||||
Color::Xyza(xyza) => xyza.into(),
|
||||
}
|
||||
}
|
||||
|
@ -455,6 +512,7 @@ impl From<Color> for Xyza {
|
|||
Color::Laba(laba) => laba.into(),
|
||||
Color::Lcha(x) => x.into(),
|
||||
Color::Oklaba(x) => x.into(),
|
||||
Color::Oklcha(oklch) => oklch.into(),
|
||||
Color::Xyza(xyza) => xyza,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,8 +39,8 @@
|
|||
//! and an analog of lightness in the form of value. In contrast, HWB instead uses whiteness and blackness
|
||||
//! parameters, which can be used to lighten and darken a particular hue respectively.
|
||||
//!
|
||||
//! Oklab is a perceptually uniform color space that is designed to be used for tasks such
|
||||
//! as image processing. It is not as widely used as the other color spaces, but it is useful
|
||||
//! Oklab and Okclch are perceptually uniform color spaces that are designed to be used for tasks such
|
||||
//! as image processing. They are not as widely used as the other color spaces, but are useful
|
||||
//! 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.
|
||||
//!
|
||||
|
@ -87,6 +87,7 @@ mod laba;
|
|||
mod lcha;
|
||||
mod linear_rgba;
|
||||
mod oklaba;
|
||||
mod oklcha;
|
||||
pub mod palettes;
|
||||
mod srgba;
|
||||
#[cfg(test)]
|
||||
|
@ -106,6 +107,7 @@ pub mod prelude {
|
|||
pub use crate::lcha::*;
|
||||
pub use crate::linear_rgba::*;
|
||||
pub use crate::oklaba::*;
|
||||
pub use crate::oklcha::*;
|
||||
pub use crate::srgba::*;
|
||||
pub use crate::xyza::*;
|
||||
}
|
||||
|
@ -120,6 +122,7 @@ pub use laba::*;
|
|||
pub use lcha::*;
|
||||
pub use linear_rgba::*;
|
||||
pub use oklaba::*;
|
||||
pub use oklcha::*;
|
||||
pub use srgba::*;
|
||||
pub use xyza::*;
|
||||
|
||||
|
@ -142,6 +145,7 @@ where
|
|||
Self: From<Laba> + Into<Laba>,
|
||||
Self: From<Lcha> + Into<Lcha>,
|
||||
Self: From<Oklaba> + Into<Oklaba>,
|
||||
Self: From<Oklcha> + Into<Oklcha>,
|
||||
Self: From<Xyza> + Into<Xyza>,
|
||||
Self: Alpha,
|
||||
{
|
||||
|
|
318
crates/bevy_color/src/oklcha.rs
Normal file
318
crates/bevy_color/src/oklcha.rs
Normal file
|
@ -0,0 +1,318 @@
|
|||
use crate::{
|
||||
color_difference::EuclideanDistance, Alpha, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba,
|
||||
Luminance, Mix, Oklaba, Srgba, StandardColor, Xyza,
|
||||
};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Color in Oklch color space, with alpha
|
||||
#[doc = include_str!("../docs/conversion.md")]
|
||||
/// <div>
|
||||
#[doc = include_str!("../docs/diagrams/model_graph.svg")]
|
||||
/// </div>
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Reflect)]
|
||||
#[reflect(PartialEq, Serialize, Deserialize)]
|
||||
pub struct Oklcha {
|
||||
/// The 'lightness' channel. [0.0, 1.0]
|
||||
pub lightness: f32,
|
||||
/// The 'chroma' channel. [0.0, 1.0]
|
||||
pub chroma: f32,
|
||||
/// The 'hue' channel. [0.0, 360.0]
|
||||
pub hue: f32,
|
||||
/// The alpha channel. [0.0, 1.0]
|
||||
pub alpha: f32,
|
||||
}
|
||||
|
||||
impl StandardColor for Oklcha {}
|
||||
|
||||
impl Oklcha {
|
||||
/// Construct a new [`Oklcha`] color from components.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lightness` - Lightness channel. [0.0, 1.0]
|
||||
/// * `chroma` - Chroma channel. [0.0, 1.0]
|
||||
/// * `hue` - Hue channel. [0.0, 360.0]
|
||||
/// * `alpha` - Alpha channel. [0.0, 1.0]
|
||||
pub const fn new(lightness: f32, chroma: f32, hue: f32, alpha: f32) -> Self {
|
||||
Self {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
alpha,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new [`Oklcha`] color from (l, c, h) components, with the default alpha (1.0).
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `lightness` - Lightness channel. [0.0, 1.0]
|
||||
/// * `chroma` - Chroma channel. [0.0, 1.0]
|
||||
/// * `hue` - Hue channel. [0.0, 360.0]
|
||||
/// * `alpha` - Alpha channel. [0.0, 1.0]
|
||||
pub const fn lch(lightness: f32, chroma: f32, hue: f32) -> Self {
|
||||
Self::new(lightness, chroma, hue, 1.0)
|
||||
}
|
||||
|
||||
/// Return a copy of this color with the 'lightness' channel set to the given value.
|
||||
pub const fn with_l(self, lightness: f32) -> Self {
|
||||
Self { lightness, ..self }
|
||||
}
|
||||
|
||||
/// Return a copy of this color with the 'chroma' channel set to the given value.
|
||||
pub const fn with_c(self, chroma: f32) -> Self {
|
||||
Self { chroma, ..self }
|
||||
}
|
||||
|
||||
/// Return a copy of this color with the 'hue' channel set to the given value.
|
||||
pub const fn with_h(self, hue: f32) -> Self {
|
||||
Self { hue, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Oklcha {
|
||||
fn default() -> Self {
|
||||
Self::new(1., 0., 0., 1.)
|
||||
}
|
||||
}
|
||||
|
||||
impl Mix for Oklcha {
|
||||
#[inline]
|
||||
fn mix(&self, other: &Self, factor: f32) -> Self {
|
||||
let n_factor = 1.0 - factor;
|
||||
Self {
|
||||
lightness: self.lightness * n_factor + other.lightness * factor,
|
||||
chroma: self.chroma * n_factor + other.chroma * factor,
|
||||
hue: self.hue * n_factor + other.hue * factor,
|
||||
alpha: self.alpha * n_factor + other.alpha * factor,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Alpha for Oklcha {
|
||||
#[inline]
|
||||
fn with_alpha(&self, alpha: f32) -> Self {
|
||||
Self { alpha, ..*self }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alpha(&self) -> f32 {
|
||||
self.alpha
|
||||
}
|
||||
}
|
||||
|
||||
impl Luminance for Oklcha {
|
||||
#[inline]
|
||||
fn with_luminance(&self, lightness: f32) -> Self {
|
||||
Self { lightness, ..*self }
|
||||
}
|
||||
|
||||
fn luminance(&self) -> f32 {
|
||||
self.lightness
|
||||
}
|
||||
|
||||
fn darker(&self, amount: f32) -> Self {
|
||||
Self::new(
|
||||
(self.lightness - amount).max(0.),
|
||||
self.chroma,
|
||||
self.hue,
|
||||
self.alpha,
|
||||
)
|
||||
}
|
||||
|
||||
fn lighter(&self, amount: f32) -> Self {
|
||||
Self::new(
|
||||
(self.lightness + amount).min(1.),
|
||||
self.chroma,
|
||||
self.hue,
|
||||
self.alpha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl EuclideanDistance for Oklcha {
|
||||
#[inline]
|
||||
fn distance_squared(&self, other: &Self) -> f32 {
|
||||
(self.lightness - other.lightness).powi(2)
|
||||
+ (self.chroma - other.chroma).powi(2)
|
||||
+ (self.hue - other.hue).powi(2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklaba> for Oklcha {
|
||||
fn from(Oklaba { l, a, b, alpha }: Oklaba) -> Self {
|
||||
let lightness = l;
|
||||
let chroma = a.hypot(b);
|
||||
let hue = b.atan2(a).to_degrees();
|
||||
|
||||
let hue = if hue < 0.0 { hue + 360.0 } else { hue };
|
||||
|
||||
Oklcha::new(lightness, chroma, hue, alpha)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Oklaba {
|
||||
fn from(
|
||||
Oklcha {
|
||||
lightness,
|
||||
chroma,
|
||||
hue,
|
||||
alpha,
|
||||
}: Oklcha,
|
||||
) -> Self {
|
||||
let l = lightness;
|
||||
let a = chroma * hue.to_radians().cos();
|
||||
let b = chroma * hue.to_radians().sin();
|
||||
|
||||
Oklaba::new(l, a, b, alpha)
|
||||
}
|
||||
}
|
||||
|
||||
// Derived Conversions
|
||||
|
||||
impl From<Hsla> for Oklcha {
|
||||
fn from(value: Hsla) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Hsla {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Hsva> for Oklcha {
|
||||
fn from(value: Hsva) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Hsva {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Hwba> for Oklcha {
|
||||
fn from(value: Hwba) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Hwba {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Laba> for Oklcha {
|
||||
fn from(value: Laba) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Laba {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Lcha> for Oklcha {
|
||||
fn from(value: Lcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Lcha {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LinearRgba> for Oklcha {
|
||||
fn from(value: LinearRgba) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for LinearRgba {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Srgba> for Oklcha {
|
||||
fn from(value: Srgba) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Srgba {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Xyza> for Oklcha {
|
||||
fn from(value: Xyza) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for Xyza {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
Oklaba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{test_colors::TEST_COLORS, testing::assert_approx_eq, Srgba};
|
||||
|
||||
#[test]
|
||||
fn test_to_from_srgba() {
|
||||
let oklcha = Oklcha::new(0.5, 0.5, 180.0, 1.0);
|
||||
let srgba: Srgba = oklcha.into();
|
||||
let oklcha2: Oklcha = srgba.into();
|
||||
assert_approx_eq!(oklcha.lightness, oklcha2.lightness, 0.001);
|
||||
assert_approx_eq!(oklcha.chroma, oklcha2.chroma, 0.001);
|
||||
assert_approx_eq!(oklcha.hue, oklcha2.hue, 0.001);
|
||||
assert_approx_eq!(oklcha.alpha, oklcha2.alpha, 0.001);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_from_srgba_2() {
|
||||
for color in TEST_COLORS.iter() {
|
||||
let rgb2: Srgba = (color.oklch).into();
|
||||
let oklch: Oklcha = (color.rgb).into();
|
||||
assert!(
|
||||
color.rgb.distance(&rgb2) < 0.0001,
|
||||
"{}: {:?} != {:?}",
|
||||
color.name,
|
||||
color.rgb,
|
||||
rgb2
|
||||
);
|
||||
assert!(
|
||||
color.oklch.distance(&oklch) < 0.0001,
|
||||
"{}: {:?} != {:?}",
|
||||
color.name,
|
||||
color.oklch,
|
||||
oklch
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_from_linear() {
|
||||
let oklcha = Oklcha::new(0.5, 0.5, 0.5, 1.0);
|
||||
let linear: LinearRgba = oklcha.into();
|
||||
let oklcha2: Oklcha = linear.into();
|
||||
assert_approx_eq!(oklcha.lightness, oklcha2.lightness, 0.001);
|
||||
assert_approx_eq!(oklcha.chroma, oklcha2.chroma, 0.001);
|
||||
assert_approx_eq!(oklcha.hue, oklcha2.hue, 0.001);
|
||||
assert_approx_eq!(oklcha.alpha, oklcha2.alpha, 0.001);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Generated by gen_tests. Do not edit.
|
||||
#[cfg(test)]
|
||||
use crate::{Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Srgba, Xyza};
|
||||
use crate::{Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Srgba, Xyza};
|
||||
|
||||
#[cfg(test)]
|
||||
pub struct TestColor {
|
||||
|
@ -13,6 +13,7 @@ pub struct TestColor {
|
|||
pub lab: Laba,
|
||||
pub lch: Lcha,
|
||||
pub oklab: Oklaba,
|
||||
pub oklch: Oklcha,
|
||||
pub xyz: Xyza,
|
||||
}
|
||||
|
||||
|
@ -30,6 +31,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(0.0, 0.0, 1.0, 1.0),
|
||||
lab: Laba::new(0.0, 0.0, 0.0, 1.0),
|
||||
oklab: Oklaba::new(0.0, 0.0, 0.0, 1.0),
|
||||
oklch: Oklcha::new(0.0, 0.0, 0.0, 1.0),
|
||||
xyz: Xyza::new(0.0, 0.0, 0.0, 1.0),
|
||||
},
|
||||
// white
|
||||
|
@ -43,6 +45,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(0.0, 1.0, 0.0, 1.0),
|
||||
lab: Laba::new(1.0, 0.0, 0.0, 1.0),
|
||||
oklab: Oklaba::new(1.0, 0.0, 0.000000059604645, 1.0),
|
||||
oklch: Oklcha::new(1.0, 0.000000059604645, 90.0, 1.0),
|
||||
xyz: Xyza::new(0.95047, 1.0, 1.08883, 1.0),
|
||||
},
|
||||
// red
|
||||
|
@ -56,6 +59,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(0.0, 1.0, 1.0, 1.0),
|
||||
hwb: Hwba::new(0.0, 0.0, 0.0, 1.0),
|
||||
lab: Laba::new(0.532408, 0.8009243, 0.6720321, 1.0),
|
||||
oklch: Oklcha::new(0.6279554, 0.2576833, 29.233892, 1.0),
|
||||
xyz: Xyza::new(0.4124564, 0.2126729, 0.0193339, 1.0),
|
||||
},
|
||||
// green
|
||||
|
@ -69,6 +73,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(120.0, 0.0, 0.0, 1.0),
|
||||
lab: Laba::new(0.8773472, -0.86182654, 0.8317931, 1.0),
|
||||
oklab: Oklaba::new(0.8664396, -0.2338874, 0.1794985, 1.0),
|
||||
oklch: Oklcha::new(0.8664396, 0.2948271, 142.49532, 1.0),
|
||||
xyz: Xyza::new(0.3575761, 0.7151522, 0.119192, 1.0),
|
||||
},
|
||||
// blue
|
||||
|
@ -82,6 +87,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(240.0, 1.0, 1.0, 1.0),
|
||||
hwb: Hwba::new(240.0, 0.0, 0.0, 1.0),
|
||||
lab: Laba::new(0.32297015, 0.7918751, -1.0786015, 1.0),
|
||||
oklch: Oklcha::new(0.45201376, 0.31321433, 264.05203, 1.0),
|
||||
xyz: Xyza::new(0.1804375, 0.072175, 0.9503041, 1.0),
|
||||
},
|
||||
// yellow
|
||||
|
@ -95,6 +101,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(60.0, 1.0, 1.0, 1.0),
|
||||
hwb: Hwba::new(60.0, 0.0, 0.0, 1.0),
|
||||
lab: Laba::new(0.9713927, -0.21553725, 0.94477975, 1.0),
|
||||
oklch: Oklcha::new(0.9679827, 0.21100593, 109.76923, 1.0),
|
||||
xyz: Xyza::new(0.7700325, 0.9278251, 0.1385259, 1.0),
|
||||
},
|
||||
// magenta
|
||||
|
@ -108,6 +115,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
lab: Laba::new(0.6032421, 0.9823433, -0.60824895, 1.0),
|
||||
lch: Lcha::new(0.6032421, 1.1554068, 328.23495, 1.0),
|
||||
oklab: Oklaba::new(0.7016738, 0.27456632, -0.16915613, 1.0),
|
||||
oklch: Oklcha::new(0.7016738, 0.32249108, 328.36343, 1.0),
|
||||
xyz: Xyza::new(0.5928939, 0.28484792, 0.969638, 1.0),
|
||||
},
|
||||
// cyan
|
||||
|
@ -121,6 +129,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(180.0, 1.0, 1.0, 1.0),
|
||||
hwb: Hwba::new(180.0, 0.0, 0.0, 1.0),
|
||||
lab: Laba::new(0.9111321, -0.4808751, -0.14131188, 1.0),
|
||||
oklch: Oklcha::new(0.9053992, 0.15454963, 194.76901, 1.0),
|
||||
xyz: Xyza::new(0.5380136, 0.78732723, 1.069496, 1.0),
|
||||
},
|
||||
// gray
|
||||
|
@ -134,6 +143,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(0.0, 0.0, 0.5, 1.0),
|
||||
hwb: Hwba::new(0.0, 0.5, 0.5, 1.0),
|
||||
lab: Laba::new(0.5338897, 0.0, 0.0, 1.0),
|
||||
oklch: Oklcha::new(0.5981808, 0.00000023841858, 0.0, 1.0),
|
||||
xyz: Xyza::new(0.2034397, 0.21404117, 0.23305441, 1.0),
|
||||
},
|
||||
// olive
|
||||
|
@ -147,6 +157,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(60.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.51677734, -0.1289308, 0.5651491, 1.0),
|
||||
oklab: Oklaba::new(0.57902855, -0.042691574, 0.11878061, 1.0),
|
||||
oklch: Oklcha::new(0.57902855, 0.12621966, 109.76922, 1.0),
|
||||
xyz: Xyza::new(0.16481864, 0.19859275, 0.029650241, 1.0),
|
||||
},
|
||||
// purple
|
||||
|
@ -160,6 +171,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(300.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.29655674, 0.58761847, -0.3638428, 1.0),
|
||||
oklab: Oklaba::new(0.41972777, 0.1642403, -0.10118592, 1.0),
|
||||
oklch: Oklcha::new(0.41972777, 0.19290791, 328.36343, 1.0),
|
||||
xyz: Xyza::new(0.12690368, 0.060969174, 0.20754242, 1.0),
|
||||
},
|
||||
// teal
|
||||
|
@ -173,6 +185,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(180.0, 1.0, 0.5, 1.0),
|
||||
hwb: Hwba::new(180.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.4807306, -0.28765023, -0.084530115, 1.0),
|
||||
oklch: Oklcha::new(0.54159236, 0.092448615, 194.76903, 1.0),
|
||||
xyz: Xyza::new(0.11515705, 0.16852042, 0.22891617, 1.0),
|
||||
},
|
||||
// maroon
|
||||
|
@ -186,6 +199,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
lab: Laba::new(0.2541851, 0.47909766, 0.37905872, 1.0),
|
||||
lch: Lcha::new(0.2541851, 0.61091745, 38.350803, 1.0),
|
||||
oklab: Oklaba::new(0.3756308, 0.13450874, 0.07527886, 1.0),
|
||||
oklch: Oklcha::new(0.3756308, 0.1541412, 29.233906, 1.0),
|
||||
xyz: Xyza::new(0.08828264, 0.045520753, 0.0041382504, 1.0),
|
||||
},
|
||||
// lime
|
||||
|
@ -199,6 +213,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
lab: Laba::new(0.46052113, -0.5155285, 0.4975627, 1.0),
|
||||
lch: Lcha::new(0.46052113, 0.71647626, 136.01596, 1.0),
|
||||
oklab: Oklaba::new(0.5182875, -0.13990697, 0.10737252, 1.0),
|
||||
oklch: Oklcha::new(0.5182875, 0.17635989, 142.49535, 1.0),
|
||||
xyz: Xyza::new(0.076536, 0.153072, 0.025511991, 1.0),
|
||||
},
|
||||
// navy
|
||||
|
@ -212,6 +227,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(240.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.12890343, 0.4736844, -0.64519864, 1.0),
|
||||
oklab: Oklaba::new(0.27038592, -0.01941514, -0.18635012, 1.0),
|
||||
oklch: Oklcha::new(0.27038592, 0.18735878, 264.05203, 1.0),
|
||||
xyz: Xyza::new(0.03862105, 0.01544842, 0.20340417, 1.0),
|
||||
},
|
||||
// orange
|
||||
|
@ -225,6 +241,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(60.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.51677734, -0.1289308, 0.5651491, 1.0),
|
||||
oklab: Oklaba::new(0.57902855, -0.042691574, 0.11878061, 1.0),
|
||||
oklch: Oklcha::new(0.57902855, 0.12621966, 109.76922, 1.0),
|
||||
xyz: Xyza::new(0.16481864, 0.19859275, 0.029650241, 1.0),
|
||||
},
|
||||
// fuchsia
|
||||
|
@ -238,6 +255,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hwb: Hwba::new(300.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.29655674, 0.58761847, -0.3638428, 1.0),
|
||||
oklab: Oklaba::new(0.41972777, 0.1642403, -0.10118592, 1.0),
|
||||
oklch: Oklcha::new(0.41972777, 0.19290791, 328.36343, 1.0),
|
||||
xyz: Xyza::new(0.12690368, 0.060969174, 0.20754242, 1.0),
|
||||
},
|
||||
// aqua
|
||||
|
@ -251,6 +269,7 @@ pub const TEST_COLORS: &[TestColor] = &[
|
|||
hsv: Hsva::new(180.0, 1.0, 0.5, 1.0),
|
||||
hwb: Hwba::new(180.0, 0.0, 0.5, 1.0),
|
||||
lab: Laba::new(0.4807306, -0.28765023, -0.084530115, 1.0),
|
||||
oklch: Oklcha::new(0.54159236, 0.092448615, 194.76903, 1.0),
|
||||
xyz: Xyza::new(0.11515705, 0.16852042, 0.22891617, 1.0),
|
||||
},
|
||||
];
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use bevy_color::{
|
||||
Color, HexColorError, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Srgba, Xyza,
|
||||
Color, HexColorError, Hsla, Hsva, Hwba, Laba, Lcha, LinearRgba, Oklaba, Oklcha, Srgba, Xyza,
|
||||
};
|
||||
|
||||
use bevy_math::{Vec3, Vec4};
|
||||
|
@ -929,6 +929,7 @@ impl From<Color> for LegacyColor {
|
|||
Color::Laba(x) => x.into(),
|
||||
Color::Lcha(x) => x.into(),
|
||||
Color::Oklaba(x) => x.into(),
|
||||
Color::Oklcha(x) => x.into(),
|
||||
Color::Xyza(x) => x.into(),
|
||||
}
|
||||
}
|
||||
|
@ -1083,6 +1084,18 @@ impl From<Oklaba> for LegacyColor {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<LegacyColor> for Oklcha {
|
||||
fn from(value: LegacyColor) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Oklcha> for LegacyColor {
|
||||
fn from(value: Oklcha) -> Self {
|
||||
LinearRgba::from(value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LegacyColor> for wgpu::Color {
|
||||
fn from(color: LegacyColor) -> Self {
|
||||
if let LegacyColor::RgbaLinear {
|
||||
|
|
Loading…
Reference in a new issue