chroma_rust/utils/
distance.rs

1use crate::Color;
2
3/// Calc simple Euclidean distance between two colors with the same mode
4///
5/// the default mode is `lab`
6pub fn distance(c1: &Color, c2: &Color, mode: Option<&str>) -> f64 {
7    let mode = match mode {
8        Some(mode) => mode,
9        None => "lab",
10    };
11
12    let c1 = c1.mode(mode);
13    let c2 = c2.mode(mode);
14
15    let mut sum_sq = 0.0;
16    c1.iter().zip(c2.iter()).for_each(|(a, b)| {
17        sum_sq += (a - b).powi(2);
18    });
19    sum_sq.sqrt()
20}
21
22#[cfg(test)]
23mod tests {
24
25    use super::*;
26
27    #[test]
28    fn test_calc_rgb_distance() {
29        let c1 = Color::from("rgb(255, 0, 0)");
30        let c2 = Color::from("rgb(0, 255, 0)");
31
32        assert_eq!(distance(&c1, &c2, Some("rgb")), 360.62445840513925);
33    }
34
35    #[test]
36    fn test_calc_lab_distance() {
37        let c1 = Color::from("rgb(255, 0, 0)");
38        let c2 = Color::from("rgb(0, 255, 0)");
39
40        // default is lab
41        assert_eq!(distance(&c1, &c2, None), 170.56524200601007);
42        assert_eq!(distance(&c1, &c2, Some("lab")), 170.56524200601007);
43
44        let c1 = Color::from("#fff");
45        let c2 = Color::from("#ff0");
46
47        assert_eq!(distance(&c1, &c2, Some("rgb")), 255.0);
48        assert_eq!(distance(&c1, &c2, Some("lab")), 96.94758206572062);
49    }
50}