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
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate bitflags;

mod color;
mod color_names;
mod colors;

use color_names::ColorNames;
use colors::basic::BasicColors;
use colors::html::HTMLColors;
use colors::ntc::NtcColors;
use colors::pantone::PantoneColors;
use colors::roygbiv::RoygbivColors;
use colors::x11::X11Colors;
use color::{Color, ColorError};

bitflags! {
    pub struct Colors: u32 {
        const BASIC   = 0b00000001;
        const HTML    = 0b00000010;
        const NTC     = 0b00000100;
        const PANTONE = 0b00001000;
        const ROYGBIV = 0b00010000;
        const X11     = 0b00100000;
    }
}

pub struct ColorNamer {
    colors: Vec<Color>
}

impl ColorNamer {
    pub fn new(colors: Colors) -> ColorNamer {
        let mut color_vec: Vec<Color> = vec![];

        if !(colors | Colors::BASIC).is_empty() {
            color_vec.append(&mut BasicColors{}.get_colors());
        }

        if !(colors | Colors::HTML).is_empty() {
            color_vec.append(&mut HTMLColors{}.get_colors());
        }

        if !(colors | Colors::NTC).is_empty() {
            color_vec.append(&mut NtcColors{}.get_colors());
        }

        if !(colors | Colors::PANTONE).is_empty() {
            color_vec.append(&mut PantoneColors{}.get_colors());
        }

        if !(colors | Colors::ROYGBIV).is_empty() {
            color_vec.append(&mut RoygbivColors{}.get_colors());
        }

        if !(colors | Colors::X11).is_empty() {
            color_vec.append(&mut X11Colors{}.get_colors());
        }

        ColorNamer {
            colors: color_vec
        }
    }

    pub fn name_hex_color(&self, hex: &str) -> Result<String, ColorError> {
        let color = color::color_from_hex("", &hex)?;
        let lab = color.to_lab();

        let mut min_distance: f32 = std::f32::MAX;
        let mut closest_color = color;

        for c in &self.colors {
            let distance = c.distance(lab);
            if distance < min_distance {
                min_distance = distance;
                closest_color = *c;
            }
        }

        Ok(closest_color.name.to_string())
    }
}