use core::marker::PhantomData;
use crate::adaptation::{Bradford, adapt};
use crate::illuminant::Illuminant;
use crate::math::Mat3;
use crate::{Asserts, Color, ColorSpace, Transform};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Xyz<W: Illuminant>(PhantomData<W>);
impl<W: Illuminant> ColorSpace for Xyz<W> {
const CHANNELS: usize = 3;
const LUMINANCE_WEIGHTS: Option<[f32; 3]> = Some([0.0, 1.0, 0.0]);
}
impl<W: Illuminant> Asserts<[f32; 3]> for Xyz<W> {}
impl<W: Illuminant> Asserts<[f32; 4]> for Xyz<W> {}
#[cfg(feature = "glam")]
impl<W: Illuminant> Asserts<glam::Vec4> for Xyz<W> {}
#[cfg(feature = "glam")]
impl<W: Illuminant> Asserts<glam::Vec3A> for Xyz<W> {}
impl<W1, W2> Transform<Color<[f32; 3], Xyz<W1>>> for Color<[f32; 3], Xyz<W2>>
where
W1: Illuminant,
W2: Illuminant,
{
fn transform_from(src: Color<[f32; 3], Xyz<W1>>, _: &()) -> Self {
const fn matrix<W1: Illuminant, W2: Illuminant>() -> Mat3 {
adapt::<Bradford>(W1::WHITE_POINT_XYZ, W2::WHITE_POINT_XYZ)
}
let x = src.inner();
let out = const { matrix::<W1, W2>() }.apply([x[0], x[1], x[2]]);
Color::new_unchecked([out[0], out[1], out[2]])
}
}
impl<W1, W2> Transform<Color<[f32; 4], Xyz<W1>>> for Color<[f32; 4], Xyz<W2>>
where
W1: Illuminant,
W2: Illuminant,
{
fn transform_from(src: Color<[f32; 4], Xyz<W1>>, _: &()) -> Self {
const fn matrix<W1: Illuminant, W2: Illuminant>() -> Mat3 {
adapt::<Bradford>(W1::WHITE_POINT_XYZ, W2::WHITE_POINT_XYZ)
}
let x = src.inner();
let out = const { matrix::<W1, W2>() }.apply([x[0], x[1], x[2]]);
Color::new_unchecked([out[0], out[1], out[2], x[3]])
}
}
impl<W: Illuminant> From<Color<[f32; 3], Xyz<W>>> for Color<[f32; 4], Xyz<W>> {
fn from(src: Color<[f32; 3], Xyz<W>>) -> Self {
let [x, y, z] = src.inner();
Color::new_unchecked([x, y, z, 1.0])
}
}
impl<W: Illuminant> From<Color<[f32; 4], Xyz<W>>> for Color<[f32; 3], Xyz<W>> {
fn from(src: Color<[f32; 4], Xyz<W>>) -> Self {
let [x, y, z, _] = src.inner();
Color::new_unchecked([x, y, z])
}
}
pub type XyzD65 = Xyz<crate::illuminant::D65>;
pub type XyzD50 = Xyz<crate::illuminant::D50>;
pub type XyzAces = Xyz<crate::illuminant::AcesWhitePoint>;