Skip to content

Commit

Permalink
use lab colorspace
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony Crisci committed May 24, 2018
1 parent 6b22d1a commit 63f4d99
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Naming things is one of the hard things in computer science.

Colornamer-rs is a library written in Rust that helps you come up with a good name for a color.

It does this by converting the color to RGB colorspace and then finding the nearest neighbor in a list of colors.
It does this by converting the color to [Lab color space](https://en.wikipedia.org/wiki/Lab_color_space) and using the Delta E formula to compare the color difference in a list of colors with known names and finding the nearest neighbor.

## Example

Expand Down Expand Up @@ -38,14 +38,16 @@ The color names are derived from several lists:
* Pantone
* ntc - an [astounding collection](http://chir.ag/projects/ntc/) of over 1500 named colors.

## TODO

* Use [Lab color space](https://en.wikipedia.org/wiki/Lab_color_space) instead of RGB.

## Acknowledgements

This library is based on the wonderful [color-namer](https://github.com/colorjs/color-namer) library for nodejs.

Color difference formulas were found at [easyrgb.com](http://www.easyrgb.com/en/math.php).

Further reading:

* [Wikipedia article for color distance](https://en.wikipedia.org/wiki/Color_difference).

## License

MIT (see LICENSE)
49 changes: 45 additions & 4 deletions src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,52 @@ pub fn color_from_triplet(name: &'static str, t: (u8, u8, u8)) -> Color {
}

impl Color {
/// http://www.easyrgb.com/en/math.php
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, other: &Self) -> f32 {
let dr = self.r - other.r;
let dg = self.g - other.g;
let db = self.b - other.b;
let (sl, sa, sb) = self.to_lab();
let (ol, oa, ob) = other.to_lab();

let dl = sl - ol;
let da = sa - oa;
let db = sb - ob;

dr*dr + dg*dg + db*db
(dl*dl + da*da + db*db).sqrt()
}
}

0 comments on commit 63f4d99

Please sign in to comment.