farbraum/spaces/
adobe98.rs

1use crate::illuminate::D65;
2use crate::spaces::{Adobe98, CieXyz, Srgb};
3use crate::{Color, Float, Into};
4
5fn linearize(v: Float) -> Float {
6    v.abs().powf(563.0 / 256.0) * v.signum()
7}
8
9impl Into<CieXyz<D65>> for Color<Adobe98> {
10    fn into(self, _: CieXyz<D65>) -> Color<CieXyz<D65>> {
11        let (r, g, b) = self.tuple();
12        let r = linearize(r);
13        let g = linearize(g);
14        let b = linearize(b);
15        Color::of(
16            0.5766690429101305 * r + 0.1855582379065463 * g + 0.1882286462349947 * b,
17            0.29734497525053605 * r + 0.6273635662554661 * g + 0.07529145849399788 * b,
18            0.02703136138641234 * r + 0.07068885253582723 * g + 0.9913375368376388 * b,
19        )
20    }
21}
22
23fn gamma(v: Float) -> Float {
24    v.abs().powf(256.0 / 563.0) * v.signum()
25}
26
27impl Into<Adobe98> for Color<CieXyz<D65>> {
28    fn into(self, _: Adobe98) -> Color<Adobe98> {
29        let (x, y, z) = self.tuple();
30        Color::of(
31            gamma(x * 2.0415879038107465 - y * 0.5650069742788596 - 0.34473135077832956 * z),
32            gamma(x * -0.9692436362808795 + y * 1.8759675015077202 + 0.04155505740717557 * z),
33            gamma(x * 0.013444280632031142 - y * 0.11836239223101838 + 1.0151749943912054 * z),
34        )
35    }
36}
37
38impl Into<Adobe98> for Color<Srgb> {
39    fn into(self, s: Adobe98) -> Color<Adobe98> {
40        self.into(CieXyz(D65)).into(s)
41    }
42}
43
44impl Into<Srgb> for Color<Adobe98> {
45    fn into(self, s: Srgb) -> Color<Srgb> {
46        self.into(CieXyz(D65)).into(s)
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use crate::spaces::{Adobe98, Srgb};
53    use crate::test_util::round_trips_srgb;
54    use crate::{Color, Float};
55
56    fn rgb(r: Float, g: Float, b: Float) -> Color<Srgb> {
57        Color::of(r, g, b)
58    }
59
60    fn a98(r: Float, g: Float, b: Float) -> Color<Adobe98> {
61        Color::of(r, g, b)
62    }
63
64    #[test]
65    fn test_adobe98() {
66        assert_almost_eq!(
67            rgb(1.0, 1.0, 1.0).into(Adobe98),
68            a98(1.0000487485, 0.9999895104, 0.99989495005),
69        );
70        assert_almost_eq!(rgb(0.0, 0.0, 0.0).into(Adobe98), a98(0.0, 0.0, 0.0));
71        assert_almost_eq!(
72            rgb(1.0, 0.0, 0.0).into(Adobe98),
73            a98(0.85865373273, -0.000124357058167, 0.000221323599465),
74        );
75    }
76
77    #[test]
78    fn test_adobe98_roundtrips() {
79        round_trips_srgb::<Adobe98>();
80    }
81}