1use crate::spaces::{util, Hsl, Srgb};
2use crate::{Color, Into};
3
4impl Into<Srgb> for Color<Hsl> {
5 fn into(self, _: Srgb) -> Color<Srgb> {
6 let (h, s, l) = self.tuple();
7
8 let h = util::normalize_hue(h);
9 let m1 = l + s * (if l < 0.5 { l } else { 1.0 - l });
10 let m2 = m1 - (m1 - l) * 2.0 * (((h / 60.0) % 2.0) - 1.0).abs();
11
12 match (h / 60.0).floor() as i32 {
13 0 => Color::of(m1, m2, 2.0 * l - m1),
14 1 => Color::of(m2, m1, 2.0 * l - m1),
15 2 => Color::of(2.0 * l - m1, m1, m2),
16 3 => Color::of(2.0 * l - m1, m2, m1),
17 4 => Color::of(m2, 2.0 * l - m1, m1),
18 5 => Color::of(m1, 2.0 * l - m1, m2),
19 _ => Color::of(2.0 * l - m1, 2.0 * l - m1, 2.0 * l - m1),
20 }
21 }
22}
23
24impl Into<Hsl> for Color<Srgb> {
25 fn into(self, _: Hsl) -> Color<Hsl> {
26 let (r, g, b) = self.tuple();
27
28 let (min, max) = util::min_max(r, g, b);
29 let s = if max == min {
30 0.0
31 } else {
32 (max - min) / (1.0 - (max + min - 1.0).abs())
33 };
34 let l = 0.5 * (max + min);
35 let h = util::calculate_hsl_hue(r, g, b, max, min);
36
37 Color::of(h, s, l)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43
44 use crate::spaces::{Hsl, Srgb};
45 use crate::test_util::round_trips_srgb;
46 use crate::{Color, Float};
47
48 fn rgb(r: Float, g: Float, b: Float) -> Color<Srgb> {
49 Color::of(r, g, b)
50 }
51
52 fn hsl(l: Float, a: Float, b: Float) -> Color<Hsl> {
53 Color::of(l, a, b)
54 }
55
56 #[test]
57 fn test_hsl_to_rgb() {
58 assert_eq!(hsl(0.0, 0.0, 0.0).into(Srgb), rgb(0.0, 0.0, 0.0));
59 assert_eq!(hsl(60.0, 0.25, 0.0).into(Srgb), rgb(0.0, 0.0, 0.0));
60 assert_eq!(hsl(0.0, 0.0, 0.5).into(Srgb), rgb(0.5, 0.5, 0.5));
61 assert_eq!(hsl(60.0, 0.0, 0.25).into(Srgb), rgb(0.25, 0.25, 0.25));
62 assert_eq!(hsl(100.0, 0.0, 0.5).into(Srgb), rgb(0.5, 0.5, 0.5));
63 }
64
65 #[test]
66 fn test_rgb_to_hsl() {
67 assert_eq!(hsl(0.0, 0.0, 0.0), rgb(0.0, 0.0, 0.0).into(Hsl));
68 assert_eq!(hsl(0.0, 0.0, 0.25), rgb(0.25, 0.25, 0.25).into(Hsl));
69
70 assert_eq!(hsl(0.0, 1.0, 0.5), rgb(1.0, 0.0, 0.0).into(Hsl));
72 assert_eq!(hsl(60.0, 1.0, 0.5), rgb(1.0, 1.0, 0.0).into(Hsl));
73 assert_eq!(hsl(120.0, 1.0, 0.5), rgb(0.0, 1.0, 0.0).into(Hsl));
74 assert_eq!(hsl(180.0, 1.0, 0.5), rgb(0.0, 1.0, 1.0).into(Hsl));
75 assert_eq!(hsl(240.0, 1.0, 0.5), rgb(0.0, 0.0, 1.0).into(Hsl));
76 assert_eq!(hsl(300.0, 1.0, 0.5), rgb(1.0, 0.0, 1.0).into(Hsl));
77 }
78
79 #[test]
80 fn test_hsl_roundtrips() {
81 round_trips_srgb::<Hsl>();
82 }
83}