use crate::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 { Pixel { r: (a.r >> 2) + (b.r >> 2), g: (a.g >> 2) + (b.g >> 2), b: (a.b >> 2) + (b.b >> 2), } } } 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 }