use crate::format::ser::{Ser, Sink, Source}; #[derive(Copy, Clone, Debug, Default)] pub struct Pixel { pub r: u8, pub g: u8, pub b: u8, } impl Ser for Pixel { fn write(&self, sink: &mut impl std::io::Write) -> anyhow::Result<()> { sink.put((self.r, self.g, self.b)) } fn read(source: &mut impl std::io::Read) -> anyhow::Result { let (r, g, b) = source.get()?; Ok(Self { r, g, b }) } } impl Pixel { pub const BLACK: Pixel = Pixel { r: 0, g: 0, b: 0 }; #[inline] pub fn distance(a: Pixel, b: Pixel) -> usize { let (rd, gd, bd) = ( a.r.abs_diff(b.r) as usize, a.r.abs_diff(b.r) as usize, a.r.abs_diff(b.r) as usize, ); SQRT[rd + gd + bd] } #[inline] pub fn average(a: Pixel, b: Pixel) -> Pixel { //? this functions is broken // TODO dont loose accuracy Pixel { r: (a.r >> 1) + (b.r >> 1), g: (a.g >> 1) + (b.g >> 1), b: (a.b >> 1) + (b.b >> 1), } } pub fn scale(&self, factor: f32) -> Pixel { Pixel { r: ((self.r as f32) * factor).clamp(0.0, 255.0) as u8, g: ((self.g as f32) * factor).clamp(0.0, 255.0) as u8, b: ((self.b as f32) * factor).clamp(0.0, 255.0) as u8, } } } const SQRT: [usize; 256 * 3] = gen_sqrt_lookup(); const fn gen_sqrt_lookup() -> [usize; N] { let mut arr = [0; N]; let mut i = 0; while i < N { arr[i] = sqrt(i as f32) as usize; i += 1; } arr } const fn sqrt(x: f32) -> f32 { let a = 1.0; let a = (a + x / a) * 0.5; let a = (a + x / a) * 0.5; let a = (a + x / a) * 0.5; a }