chroma_rust/color/
spaces.rs

1use crate::{utils::conversion, Color};
2
3impl Color {
4    /// Return the color as hexadecimal string.
5    ///
6    /// The hex string will include the alpha channel if it's less than 1.
7    ///
8    /// For example:
9    /// ```
10    /// use chroma_rust::Color;
11    /// let color = Color::from("#abcdef");
12    /// assert_eq!(color.hex(), "#abcdef");
13    /// let color = Color::from("rgba(255, 255, 255, 0.6)");
14    /// assert_eq!(color.hex(), "#ffffff99");
15    /// ```
16    pub fn hex(&self) -> String {
17        conversion::hex::rgb2hex(self.rgba())
18    }
19
20    pub fn rgb(&self) -> (u8, u8, u8) {
21        let (r, g, b, _) = self.rgba;
22        (r, g, b)
23    }
24
25    pub fn rgba(&self) -> (u8, u8, u8, f64) {
26        self.rgba
27    }
28
29    pub fn hsl(&self) -> (f64, f64, f64) {
30        conversion::hsl::rgb2hsl(self.rgb())
31    }
32
33    pub fn hsv(&self) -> (f64, f64, f64) {
34        conversion::hsv::rgb2hsv(self.rgb())
35    }
36
37    pub fn hsla(&self) -> (f64, f64, f64, f64) {
38        let (h, s, l) = self.hsl();
39        let a = self.alpha();
40        (h, s, l, a)
41    }
42
43    pub fn lab(&self) -> (f64, f64, f64) {
44        conversion::lab::rgb2lab(self.rgb())
45    }
46
47    /// CMYK (cyan, magenta, yellow, black)
48    ///
49    /// <https://en.wikipedia.org/wiki/CMYK_color_model>
50    ///
51    /// <https://www.rapidtables.com/convert/color/rgb-to-cmyk.html>
52    ///
53    /// Each value is in the range [0, 1]
54    pub fn cmyk(&self) -> (f64, f64, f64, f64) {
55        conversion::cmyk::rgb2cmyk(self.rgb())
56    }
57
58    /// Returns the numeric representation of the hexadecimal RGB color.
59    ///
60    /// For example:
61    /// ```
62    /// use chroma_rust::Color;
63    /// let color = Color::from("#abcdef");
64    /// assert_eq!(color.num(), 11259375);
65    /// ```
66    pub fn num(&self) -> u32 {
67        conversion::num::rgb2num(self.rgb())
68    }
69
70    /// Returns the named color.
71    ///
72    /// Falls back to hexadecimal RGB string, if the color isn't present.
73    ///
74    /// Named color from [*w3cx11*](http://www.w3.org/TR/css3-color/#svg-color)
75    ///
76    /// ```
77    /// use chroma_rust::Color;
78    ///
79    /// let color = Color::from("#ff0");
80    /// assert_eq!(color.name(), "yellow");
81    ///
82    /// let color = Color::from("#abcdef");
83    /// assert_eq!(color.name(), "#abcdef");
84    /// ```
85    pub fn name(&self) -> String {
86        let hex = self.hex();
87
88        let result = crate::W3CX11
89            .clone()
90            .into_iter()
91            .find(|(_k, v)| v.to_string() == hex);
92
93        match result {
94            Some((k, _v)) => String::from(k),
95            None => hex,
96        }
97    }
98
99    /// Estimate the temperature in Kelvin of any given color, though this makes the only sense for colors from the temperature gradient above.
100    /// More see [color-temperature](https://github.com/neilbartlett/color-temperature).
101    pub fn temperature(&self) -> f64 {
102        conversion::temperature::rgb2temperature(self.rgb())
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn test_hex() {
112        let color = Color::new(255, 255, 255, 1.0);
113        assert_eq!(color.hex(), "#ffffff");
114
115        let color = Color::new(255, 255, 255, 0.5);
116        assert_eq!(color.hex(), "#ffffff80");
117    }
118
119    #[test]
120    fn test_rgb() {
121        let color = Color::from("orange");
122        assert_eq!(color.rgb(), (255, 165, 0));
123    }
124
125    #[test]
126    fn test_rgba() {
127        let color = Color::new(255, 255, 255, 1.0);
128        assert_eq!(color.rgba(), (255, 255, 255, 1.0));
129    }
130
131    #[test]
132    fn test_hsl() {
133        let color = Color::from("cyan");
134        let (h, s, l) = color.hsl();
135        assert_eq!(h, 180.0);
136        assert_eq!(s, 1.0);
137        assert_eq!(l, 0.5);
138    }
139
140    #[test]
141    fn test_hsv() {
142        let color = Color::from("cyan");
143        let (h, s, v) = color.hsv();
144        assert_eq!(h, 180.0);
145        assert_eq!(s, 1.0);
146        assert_eq!(v, 1.0);
147    }
148
149    #[test]
150    fn test_hsla() {
151        let color = Color::new(255, 255, 255, 1.0);
152        let (h, s, l, a) = color.hsla();
153        assert_eq!(h, 0.0);
154        assert_eq!(s, 0.0);
155        assert_eq!(l, 1.0);
156        assert_eq!(a, 1.0);
157    }
158
159    #[test]
160    fn test_lab() {
161        let color = Color::from("orange");
162        let (l, a, b) = color.lab();
163        // [74.94,23.93,78.95]
164        assert!(l - 74.94 < 0.01);
165        assert!(a - 23.93 < 0.01);
166        assert!(b - 78.95 < 0.01);
167    }
168
169    #[test]
170    fn test_name() {
171        let color = Color::from("#abcdef");
172        assert_eq!(color.name(), "#abcdef");
173
174        let color = Color::from("rgb(0, 250, 154)");
175        assert_eq!(color.name(), "mediumspringgreen");
176
177        let color = Color::from("#00fa9a");
178        assert_eq!(color.name(), "mediumspringgreen");
179    }
180
181    #[test]
182    fn test_num() {
183        let color = Color::from("#abcdef");
184        assert_eq!(color.num(), 11259375);
185
186        let color = Color::from("rgb(255, 128, 44)");
187        assert_eq!(color.num(), 16744492);
188    }
189
190    #[test]
191    fn test_temperature() {
192        let color = Color::from("#abcdef");
193        assert_eq!(color.temperature(), 14098.);
194
195        let color = Color::from("rgb(255, 128, 44)");
196        assert_eq!(color.temperature(), 2208.);
197
198        let color = Color::from("#b3ccff");
199        assert_eq!(color.temperature(), 15005.);
200
201        let color = Color::from("#ff0000");
202        assert_eq!(color.temperature(), 1000.);
203
204        let color = Color::from("#00ff00");
205        assert_eq!(color.temperature(), 40000.);
206
207        let color = Color::from("#0000ff");
208        assert_eq!(color.temperature(), 40000.);
209
210        let color = Color::from("#000000");
211        assert_eq!(color.temperature(), 40000.);
212    }
213
214    #[test]
215    fn test_cmyk() {
216        let color = Color::from("#cc33ff");
217        assert_eq!(color.cmyk(), (0.2, 0.8, 0., 0.));
218
219        let color = Color::from("rgb(255, 128, 44)");
220        assert_eq!(color.cmyk(), (0.0, 0.5, 0.83, 0.0));
221    }
222}