From 2a6b1e4d605df39e6cc8989dab67c00ae84ecf86 Mon Sep 17 00:00:00 2001 From: leiserfg Date: Sat, 14 Nov 2020 18:38:42 +0100 Subject: [PATCH] Use cie2000 to improve results --- Cargo.toml | 3 +++ src/color.rs | 73 ++++++++++------------------------------------------ src/lib.rs | 3 +-- 3 files changed, 17 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 986e89f..34d94d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,10 +8,13 @@ license = "MIT" [dependencies] lazy_static = "1.0" bitflags = "1.0" +delta_e = "0.2" +lab = "0.7" [dev-dependencies] criterion = "0.1.2" + [[bench]] name = "basic" harness = false diff --git a/src/color.rs b/src/color.rs index 9b7e4db..8d5fa33 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,15 +1,17 @@ use std::collections::HashMap; +extern crate delta_e; +extern crate lab; + + #[derive(Copy, Clone, Debug)] pub struct Color { - pub r: f32, - pub g: f32, - pub b: f32, + pub lab: lab::Lab, pub name: &'static str } lazy_static! { - static ref HEX_ALPHABETS: HashMap = { + static ref HEX_ALPHABETS: HashMap = { let mut m = HashMap::new(); m.insert('0', 0); m.insert('1', 1); @@ -43,7 +45,7 @@ pub fn color_from_hex(name: &'static str, hex: &str) -> Result = vec![]; + let mut value: [u8; 3] = [0, 0, 0]; if hex_vec.len() < 6 { return Err(ColorError::InvalidColorError); @@ -58,75 +60,26 @@ pub fn color_from_hex(name: &'static str, hex: &str) -> Result Color { Color { - r: t.0 as f32, - g: t.1 as f32, - b: t.2 as f32, + lab: lab::Lab::from_rgb(&[t.0, t.1, t.2]), name, } } impl Color { - /// http://www.easyrgb.com/en/math.php - pub fn to_lab(&self) -> (f32, f32, f32) { - let xyz_normalize = |c: f32| { - let c_normal = c / 255.0; - if c_normal > 0.04045 { - ((c_normal + 0.055) / 1.055).powf(2.4) - } else { - c_normal / 12.92 - } - }; - - let r = xyz_normalize(self.r); - let g = xyz_normalize(self.g); - let b = xyz_normalize(self.b); - - let x = r * 0.4124 + g * 0.3576 + b * 0.1805; - let y = r * 0.2126 + g * 0.7152 + b * 0.0722; - let z = r * 0.0193 + g * 0.1192 + b * 0.9505; - - let lab_normalize = |c: f32| { - if c > 0.008856 { - c.powf(1.0 / 3.0) - } else { - 7.787 * c + 16.0 / 116.0 - } - }; - - let lx = lab_normalize(x); - let ly = lab_normalize(y); - let lz = lab_normalize(z); - - let l = 116.0 * ly - 16.0; - let a = 500.0 * (lx - ly); - let b = 200.0 * (ly - lz); - - (l, a, b) - } - - pub fn distance(&self, lab: (f32, f32, f32)) -> f32 { - let (sl, sa, sb) = self.to_lab(); - let (ol, oa, ob) = lab; - - let dl = sl - ol; - let da = sa - oa; - let db = sb - ob; - - (dl*dl + da*da + db*db).sqrt() + pub fn distance(&self, color: Color) -> f32 { + delta_e::DE2000::new(self.lab, color.lab) } } diff --git a/src/lib.rs b/src/lib.rs index ad533a7..902b23b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,13 +66,12 @@ impl ColorNamer { pub fn name_hex_color(&self, hex: &str) -> Result { 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); + let distance = c.distance(color); if distance < min_distance { min_distance = distance; closest_color = *c;