#![doc = include_str!("../README.md")]
#![allow(clippy::excessive_precision)]
#![allow(clippy::needless_doctest_main)]
pub mod gamma;
pub mod xyz;
mod maths;
#[doc(hidden)]
pub fn normalised_from_u8(encoded: impl Into<[u8; 3]>) -> [f32; 3] {
encoded.into().map(|v| v as f32 / 255.0)
}
#[doc(hidden)]
pub fn u8_from_normalised(normalised: impl Into<[f32; 3]>) -> [u8; 3] {
normalised.into().map(|v| v.clamp(0.0, 1.0).mul_add(255.0, 0.5) as u8)
}
pub fn u8_from_xyz(xyz: impl Into<[f32; 3]>) -> [u8; 3] {
gamma::u8_from_linear(xyz::linear_from_xyz(xyz))
}
pub fn xyz_from_u8(rgb: impl Into<[u8; 3]>) -> [f32; 3] {
xyz::xyz_from_linear(gamma::linear_from_u8(rgb))
}
pub fn normalised_from_xyz(xyz: impl Into<[f32; 3]>) -> [f32; 3] {
gamma::normalised_from_linear(xyz::linear_from_xyz(xyz))
}
pub fn xyz_from_normalised(rgb: impl Into<[f32; 3]>) -> [f32; 3] {
xyz::xyz_from_linear(gamma::linear_from_normalised(rgb))
}
#[cfg(test)]
mod test {
use kahan::KahanSummator;
const WHITE_X: f64 = 0.312713;
const WHITE_Y: f64 = 0.329016;
fn measure_grey_chromaticity_error(f: impl Fn(u8) -> [f32; 3]) -> f64 {
let mut error = kahan::KahanSum::new();
for i in 1..=255 {
let [x, y, z] = f(i);
let d: f64 =
[x as f64, y as f64, z as f64].iter().kahan_sum().sum();
let x = x as f64 / d - WHITE_X;
let y = y as f64 / d - WHITE_Y;
error += x * x;
error += y * y;
}
error.sum() * 1e15
}
#[test]
fn test_grey_chromaticity_error_u8() {
assert_eq!(
48.99296021015466,
measure_grey_chromaticity_error(|i| {
super::xyz_from_u8([i, i, i])
})
);
}
#[test]
fn test_grey_chromaticity_error_normalised() {
assert_eq!(
39.81365168327802,
measure_grey_chromaticity_error(|i| {
let v = i as f32 / 255.0;
super::xyz_from_normalised([v, v, v])
})
);
}
#[test]
fn test_grey_chromaticity_error_linear() {
assert_eq!(
50.927415198412874,
measure_grey_chromaticity_error(|i| {
let v = i as f32 / 255.0;
crate::xyz::xyz_from_linear([v, v, v])
})
);
}
}