1pub fn rgb_to_hsv_64(c: (f64, f64, f64)) -> (f64, f64, f64) {
2 let p = if c.2 > c.1 {
3 (c.2, c.1, -1.0, 2.0 / 3.0)
4 } else {
5 (c.1, c.2, 0.0, -1.0 / 3.0)
6 };
7 let q = if p.0 > c.0 {
8 (p.0, p.1, p.3, c.0)
9 } else {
10 (c.0, p.1, p.2, p.0)
11 };
12 let d = q.0 - q.3.min(q.1);
13 let e: f64 = 1.0e-10;
14 return (
15 (q.2 + (q.3 - q.1) / (6.0 * d + e)).abs(),
16 d / (q.0 + e),
17 q.0,
18 );
19}
20
21pub fn hsv_to_rgb_64(c: (f64, f64, f64)) -> (f64, f64, f64) {
22 let p = (
23 ((c.0 + 1.0).fract() * 6.0 - 3.0).abs(),
24 ((c.0 + 2.0 / 3.0).fract() * 6.0 - 3.0).abs(),
25 ((c.0 + 1.0 / 3.0).fract() * 6.0 - 3.0).abs(),
26 );
27 return (
28 c.2 * mix_64(1.0, (p.0 - 1.0).clamp(0.0, 1.0), c.1),
29 c.2 * mix_64(1.0, (p.1 - 1.0).clamp(0.0, 1.0), c.1),
30 c.2 * mix_64(1.0, (p.2 - 1.0).clamp(0.0, 1.0), c.1),
31 );
32}
33
34pub fn mix_64(a: f64, b: f64, t: f64) -> f64 {
35 a * (1. - t) + b * t
36}
37
38pub fn rgb_to_hsv(c: (f32, f32, f32)) -> (f32, f32, f32) {
39 let p = if c.2 > c.1 {
40 (c.2, c.1, -1.0, 2.0 / 3.0)
41 } else {
42 (c.1, c.2, 0.0, -1.0 / 3.0)
43 };
44 let q = if p.0 > c.0 {
45 (p.0, p.1, p.3, c.0)
46 } else {
47 (c.0, p.1, p.2, p.0)
48 };
49 let d = q.0 - q.3.min(q.1);
50 let e: f32 = 1.0e-10;
51 return (
52 (q.2 + (q.3 - q.1) / (6.0 * d + e)).abs(),
53 d / (q.0 + e),
54 q.0,
55 );
56}
57
58pub fn hsv_to_rgb(c: (f32, f32, f32)) -> (f32, f32, f32) {
59 let p = (
60 ((c.0 + 1.0).fract() * 6.0 - 3.0).abs(),
61 ((c.0 + 2.0 / 3.0).fract() * 6.0 - 3.0).abs(),
62 ((c.0 + 1.0 / 3.0).fract() * 6.0 - 3.0).abs(),
63 );
64 return (
65 c.2 * mix(1.0, (p.0 - 1.0).clamp(0.0, 1.0), c.1),
66 c.2 * mix(1.0, (p.1 - 1.0).clamp(0.0, 1.0), c.1),
67 c.2 * mix(1.0, (p.2 - 1.0).clamp(0.0, 1.0), c.1),
68 );
69}
70
71pub fn mix(a: f32, b: f32, t: f32) -> f32 {
72 a * (1. - t) + b * t
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_mix() {
81 let (a, b) = (1., 2.);
82 assert_eq!(mix(a, b, 0.5), 1.5);
83 }
84
85 #[test]
86 fn convert() {
87 let rgb = (1.0, 0.0, 0.0);
88 let hsv = rgb_to_hsv(rgb);
89 assert_eq!(hsv, (0.0, 1.0, 1.0));
90 let bak = hsv_to_rgb(hsv);
91 assert_eq!(rgb, bak);
92
93 let rgb = (1.0, 1.0, 1.0);
94 let hsv = rgb_to_hsv(rgb);
95 assert_eq!(hsv, (0.0, 0.0, 1.0));
96 let bak = hsv_to_rgb(hsv);
97 assert_eq!(rgb, bak);
98 }
99}