palette/cam16/math/
chromaticity.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::{
    bool_mask::{LazySelect, Select},
    cam16::{
        math::{self, DependentParameters},
        BakedParameters,
    },
    num::{Arithmetics, FromScalar, PartialCmp, Real, Sqrt, Zero},
};

/// One the apparent chromatic intensity metrics of CAM16.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub(crate) enum ChromaticityType<T> {
    /// The [chroma](https://en.wikipedia.org/wiki/Colorfulness#Chroma) (C) of a
    /// color.
    Chroma(T),

    /// The [colorfulness](https://en.wikipedia.org/wiki/Colorfulness) (M) of a
    /// color.
    Colorfulness(T),

    /// The [saturation](https://en.wikipedia.org/wiki/Colorfulness#Saturation)
    /// (s) of a color.
    Saturation(T),
}

impl<T> ChromaticityType<T> {
    pub(crate) fn into_cam16<Wp>(
        self,
        lightness: T,
        parameters: BakedParameters<Wp, T::Scalar>,
    ) -> (T, T, T)
    where
        T: Real + FromScalar + Zero + Arithmetics + Sqrt + PartialCmp + Clone,
        T::Mask: LazySelect<T> + Clone,
    {
        let DependentParameters { c, a_w, f_l_4, .. } = parameters.inner;
        let is_black = lightness.eq(&T::zero());

        match self {
            ChromaticityType::Chroma(chroma) => {
                let colorfulness = lazy_select! {
                    if is_black.clone() => T::zero(),
                    else => math::chroma_to_colorfulness(chroma.clone(), T::from_scalar(f_l_4))
                };
                let saturation = lazy_select! {
                        if is_black.clone() => T::zero(),
                        else => math::chroma_to_saturation(
                        chroma.clone(),
                        lightness,
                        T::from_scalar(c),
                        T::from_scalar(a_w),
                    )
                };
                let chroma = is_black.select(T::zero(), chroma);

                (chroma, colorfulness, saturation)
            }
            ChromaticityType::Colorfulness(colorfulness) => {
                let chroma = lazy_select! {
                    if is_black.clone() => T::zero(),
                    else => math::colorfulness_to_chroma(colorfulness.clone(), T::from_scalar(f_l_4))
                };
                let saturation = lazy_select! {
                        if is_black.clone() => T::zero(),
                        else => math::chroma_to_saturation(
                        chroma.clone(),
                        lightness,
                        T::from_scalar(c),
                        T::from_scalar(a_w),
                    )
                };
                let colorfulness = is_black.select(T::zero(), colorfulness);

                (chroma, colorfulness, saturation)
            }
            ChromaticityType::Saturation(saturation) => {
                let chroma = lazy_select! {
                        if is_black.clone() => T::zero(),
                        else => math::saturation_to_chroma(
                        saturation.clone(),
                        lightness,
                        T::from_scalar(c),
                        T::from_scalar(a_w),
                    )
                };
                let colorfulness = lazy_select! {
                    if is_black.clone() => T::zero(),
                    else => math::chroma_to_colorfulness(chroma.clone(), T::from_scalar(f_l_4))
                };
                let saturation = is_black.select(T::zero(), saturation);

                (chroma, colorfulness, saturation)
            }
        }
    }
}