pub type Palette = [RGB<u8>];
use super::{Error, RGB};
pub mod cga;
pub mod crayon;
mod tests;
pub fn parse<T: std::iter::FromIterator<RGB<u8>>>(s: &str) -> Result<T, Error> {
use std::str::FromStr;
let filtered: Vec<&str> = s
.lines()
.map(str::trim)
.filter(|line| {
!(line.is_empty() || line.starts_with("//") || line.chars().all(char::is_whitespace))
})
.collect();
if filtered.len() <= 2 {
Err(Error::PaletteTooSmall)
} else {
filtered.into_iter().map(RGB::<u8>::from_str).collect()
}
}
pub fn quantize(palette: &Palette) -> impl Fn(RGB<f64>) -> (RGB<f64>, RGB<f64>) {
let palette = palette.to_vec();
move |RGB(r0, g0, b0)| {
let mut min_abs_err = std::f64::INFINITY;
let (mut nearest_neighbor, mut dist_from_neighbor) = (RGB(0., 0., 0.), RGB(0., 0., 0.));
for RGB(r1, g1, b1) in palette.iter().cloned().map(RGB::<f64>::from) {
let abs_err = f64::abs(r0 - r1) + f64::abs(g0 - g1) + f64::abs(b0 - b1);
if abs_err < min_abs_err {
dist_from_neighbor = RGB(r0 - r1, g0 - g1, b0 - b1);
nearest_neighbor = RGB(r1, g1, b1);
min_abs_err = abs_err;
}
}
(nearest_neighbor, dist_from_neighbor)
}
}