rgb_hsv/
lib.rs

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}