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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
use super::*;
impl From<&Hsla> for Rgba {
fn from(hsla: &Hsla) -> Rgba {
let hue = hsla.hue() / 360;
let sat = hsla.sat();
let lum = hsla.lum();
if sat.is_zero() {
let gray = lum * 255;
Rgba::new(gray, gray, gray, hsla.alpha())
} else {
fn hue2rgb(p: Rational, q: Rational, t: Rational) -> Rational {
let t = (t - t.floor()) * 6;
match t.to_integer() {
0 => p + (q - p) * t,
1 | 2 => q,
3 => p + (p - q) * (t - 4),
_ => p,
}
}
let q = if lum < Rational::new(1, 2) {
lum * (sat + 1)
} else {
lum + sat - lum * sat
};
let p = lum * 2 - q;
Rgba::new(
hue2rgb(p, q, hue + Rational::new(1, 3)) * 255,
hue2rgb(p, q, hue) * 255,
hue2rgb(p, q, hue - Rational::new(1, 3)) * 255,
hsla.alpha(),
)
}
}
}
impl From<&Hwba> for Rgba {
fn from(hwba: &Hwba) -> Rgba {
(&Hsla::from(hwba)).into()
}
}
impl From<&Hwba> for Hsla {
fn from(hwba: &Hwba) -> Hsla {
let w = hwba.whiteness();
let b = hwba.blackness();
let l = (Rational::one() - b + w) / 2;
let s = if l.is_zero() || l.is_one() {
zero()
} else {
(Rational::one() - b - l) / std::cmp::min(l, Rational::one() - l)
};
Hsla::new(hwba.hue(), s, l, hwba.alpha())
}
}
impl From<&Rgba> for Hsla {
fn from(rgba: &Rgba) -> Hsla {
let (red, green, blue) =
(rgba.red() / 255, rgba.green() / 255, rgba.blue() / 255);
let (max, min, largest) = max_min_largest(red, green, blue);
if max == min {
Hsla::new(zero(), zero(), max, rgba.alpha())
} else {
let d = max - min;
let hue = match largest {
0 => (green - blue) / d + if green < blue { 6 } else { 0 },
1 => (blue - red) / d + 2,
_ => (red - green) / d + 4,
} * (360 / 6);
let mm = max + min;
let sat = d / if mm > one() { -mm + 2 } else { mm };
Hsla::new(hue, sat, mm / 2, rgba.alpha())
}
}
}
impl From<&Rgba> for Hwba {
fn from(rgba: &Rgba) -> Hwba {
let hsla = Hsla::from(rgba);
let arr = [rgba.red(), rgba.blue(), rgba.green()];
Hwba::new(
hsla.hue(),
*arr.iter().min().unwrap() / 255,
Rational::one() - *arr.iter().max().unwrap() / 255,
hsla.alpha(),
)
}
}
impl From<&Hsla> for Hwba {
fn from(hsla: &Hsla) -> Hwba {
let rgba = Rgba::from(hsla);
let arr = [rgba.red(), rgba.blue(), rgba.green()];
Hwba::new(
hsla.hue(),
Rational::one() - *arr.iter().max().unwrap() / 255,
*arr.iter().min().unwrap() / 255,
hsla.alpha(),
)
}
}
fn max_min_largest(
a: Rational,
b: Rational,
c: Rational,
) -> (Rational, Rational, u32) {
let v = [(a, 0), (b, 1), (c, 2)];
let max = v.iter().max().unwrap();
let min = v.iter().min().unwrap();
(max.0, min.0, max.1)
}