use crate::lab::Lab;
use crate::xyz::{Illumination, XYZ};
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct RGB {
pub r: f32,
pub g: f32,
pub b: f32,
}
impl RGB {
pub fn from_hex(hex: &str) -> Result<RGB, std::num::ParseIntError> {
let hex = hex.trim_start_matches("#");
let v = u32::from_str_radix(hex, 16)?;
Ok(RGB{
r: ((v >> 16) & 0xFF) as f32,
g: ((v >> 8) & 0xFF) as f32,
b: (v & 0xFF) as f32,
})
}
pub fn xyz(self, illumination: Illumination) -> XYZ {
let r = inverse_gamma(linearize(self.r));
let g = inverse_gamma(linearize(self.g));
let b = inverse_gamma(linearize(self.b));
let x = illumination.x[0] * r + illumination.x[1] * g + illumination.x[2] * b;
let y = illumination.y[0] * r + illumination.y[1] * g + illumination.y[2] * b;
let z = illumination.z[0] * r + illumination.z[1] * g + illumination.z[2] * b;
XYZ { x, y, z }
}
pub fn lab(self, illumination: Illumination) -> Lab {
self.xyz(illumination).lab(illumination)
}
}
fn linearize(v: f32) -> f32 {
f32::min(v, 255.0) / 255.0
}
fn inverse_gamma(v: f32) -> f32 {
if v < 0.04045 {
v * 0.0773993808
} else {
f32::powf((v + 0.055) * 0.9478672986, 2.4)
}
}