1 use core::ColorInterface;
2 use core::rgb::RGB;
3 
4 #[derive(Debug, Copy, Clone, PartialEq)]
5 pub struct HSL {
6     // range 0 ≤ H < 1.0, 0 ≤ S ≤ 1.0 and 0 ≤ L ≤ 1.0:
7     pub h: f32,
8     s: f32,
9     l: f32,
10 }
11 
12 impl HSL {
new(h: f32, s: f32, l: f32) -> HSL13     pub fn new(h: f32, s: f32, l: f32) -> HSL {
14         HSL { h: _round(h), s: _round(s), l: _round(l) }
15     }
16 
hsl_to_rgb(&self) -> RGB17     pub fn hsl_to_rgb(&self) -> RGB {
18         let red: f32;
19         let green: f32;
20         let blue: f32;
21         let var_1: f32;
22         let var_2: f32;
23         if self.s == 0.0 {
24             let tmp = self.l * 255.0;
25             red = tmp;
26             green = tmp;
27             blue = tmp;
28         } else {
29             if self.l < 0.5 {
30                 var_2 = self.l * (1.0 + self.s);
31             } else {
32                 var_2 = (self.l + self.s) - (self.s * self.l);
33             }
34             var_1 = 2.0 * self.l - var_2;
35             red = 255.0 * hue_2_rgb(var_1, var_2, &mut (self.h + (1.0 / 3.0)));
36             green = 255.0 * hue_2_rgb(var_1, var_2, &mut self.h.clone());
37             blue = 255.0 * hue_2_rgb(var_1, var_2, &mut (self.h - (1.0 / 3.0)));
38         }
39         RGB::new(red.round() as u8, green.round() as u8, blue.round() as u8)
40     }
41 }
42 
43 impl ColorInterface for HSL {
to_color_str(&self) -> String44     fn to_color_str(&self) -> String {
45         self.hsl_to_rgb().to_color_str()
46     }
to_hsl(&self) -> HSL47     fn to_hsl(&self) -> HSL { *self }
48 }
49 
hue_2_rgb(v1: f32, v2: f32, vh: &mut f32) -> f3250 fn hue_2_rgb(v1: f32, v2: f32, vh: &mut f32) -> f32 {
51     if *vh < 0.0 {
52         *vh += 1.0;
53     }
54     if *vh > 1.0 {
55         *vh -= 1.0;
56     }
57     if 6.0 * *vh < 1.0 {
58         return v1 + (v2 - v1) * 6.0 * *vh;
59     }
60     if 2.0 * *vh < 1.0 {
61         return v2;
62     }
63     if 3.0 * *vh < 2.0 {
64         return v1 + (v2 - v1) * (2.0 / 3.0 - *vh) * 6.0;
65     }
66     v1
67 }
68 
_round(value: f32) -> f3269 fn _round(value: f32) -> f32 {
70     if value < 0.0 {
71         0.0
72     } else if value >= 1.0 {
73         1.0
74     } else {
75         value
76     }
77 }
78 
79 #[cfg(test)]
80 mod tests {
81     use super::*;
82 
83     #[test]
test_hsl_2_rgb_1()84     fn test_hsl_2_rgb_1() {
85         let hsl = HSL::new(0.7, 0.50, 0.60);
86         let rgb = RGB::new(122, 102, 204);
87 
88         assert_eq!(rgb, hsl.hsl_to_rgb());
89     }
90 
91     #[test]
test_hsl_2_rgb_2()92     fn test_hsl_2_rgb_2() {
93         let hsl = HSL::new(0.7, 0.0, 0.60);
94         let rgb = RGB::new(153, 153, 153);
95         assert_eq!(rgb, hsl.hsl_to_rgb());
96     }
97 
98     #[test]
test_hsl_2_rgb_3()99     fn test_hsl_2_rgb_3() {
100         let hsl = HSL::new(0.7, 0.50, 0.30);
101         let rgb = RGB::new(54, 38, 115);
102 
103         assert_eq!(rgb, hsl.hsl_to_rgb());
104     }
105 }