use super::ToLab;
impl ToLab for (f32, f32, f32) {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) { *self }
}
impl ToLab for [f32; 3] {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) { (self[0], self[1], self[2]) }
}
#[cfg(feature = "lab")]
impl ToLab for lab::Lab {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) { (self.l, self.a, self.b) }
}
#[cfg(all(feature = "lab", feature = "rgb"))]
impl ToLab for rgb::RGB<u8> {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) {
lab::Lab::from_rgb(&[self.r, self.g, self.b]).to_lab()
}
}
#[cfg(all(feature = "lab", feature = "rgb"))]
impl ToLab for rgb::alt::BGR<u8> {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) {
lab::Lab::from_rgb(&[self.r, self.g, self.b]).to_lab()
}
}
#[cfg(feature = "rgb")]
impl ToLab for rgb::alt::Gray<u8> {
#[inline]
fn to_lab(&self) -> (f32, f32, f32) { lab_from_grey(**self) }
}
#[cfg(feature = "rgb")]
fn lab_from_grey(grey: u8) -> (f32, f32, f32) {
let l = if grey <= 10 {
const KAPPA_OVER_D: f32 = 243890.0 / 889542.0;
grey as f32 * KAPPA_OVER_D
} else {
const A: f32 = 0.055 * 255.0;
const D: f32 = 1.055 * 255.0;
let ys = (grey as f32 + A) / D;
if grey <= 23 {
const KAPPA: f32 = 24389.0 / 27.0;
KAPPA * ys.powf(2.4)
} else {
116.0 * ys.powf(24.0 / 30.0) - 16.0
}
};
(l, 0.0, 0.0)
}
#[cfg(feature = "rgb")]
#[test]
fn test_lab_from_grey() {
let errors = (0..=255)
.filter_map(|grey| {
let want = lab::Lab::from_rgb(&[grey, grey, grey]).l;
let got = lab_from_grey(grey).0;
if approx::abs_diff_eq!(want, got, epsilon = 0.00001) {
None
} else {
Some((grey, want, got))
}
})
.collect::<Vec<_>>();
assert!(errors.is_empty(), "{:?}", errors);
}