#[derive(Copy, Clone, PartialEq, Eq)] #[repr(transparent)] pub struct Pixel(pub [u8; N]); impl Pixel { #[inline] pub const fn new() -> Self { Self([0; N]) } #[inline] pub fn read(&mut self, s: &[u8]) { let mut i = 0; while i < N { self.0[i] = s[i]; i += 1; } } #[inline] pub fn update_rgb(&mut self, r: u8, g: u8, b: u8) { self.0[0] = r; self.0[1] = g; self.0[2] = b; } #[inline] pub fn update_rgba(&mut self, r: u8, g: u8, b: u8, a: u8) { self.0[0] = r; self.0[1] = g; self.0[2] = b; if N >= 4 { self.0[3] = a; } } #[inline] pub fn update_diff(&mut self, b1: u8) { self.0[0] = self.0[0].wrapping_add((b1 >> 4) & 0x03).wrapping_sub(2); self.0[1] = self.0[1].wrapping_add((b1 >> 2) & 0x03).wrapping_sub(2); self.0[2] = self.0[2].wrapping_add(b1 & 0x03).wrapping_sub(2); } #[inline] pub fn update_luma(&mut self, b1: u8, b2: u8) { let vg = (b1 & 0x3f).wrapping_sub(32); let vg_8 = vg.wrapping_sub(8); let vr = vg_8.wrapping_add((b2 >> 4) & 0x0f); let vb = vg_8.wrapping_add(b2 & 0x0f); self.0[0] = self.0[0].wrapping_add(vr); self.0[1] = self.0[1].wrapping_add(vg); self.0[2] = self.0[2].wrapping_add(vb); } #[inline] pub const fn as_rgba(self, with_a: u8) -> Pixel<4> { let mut i = 0; let mut out = Pixel::new(); while i < N { out.0[i] = self.0[i]; i += 1; } if N < 4 { out.0[3] = with_a; } out } #[inline] pub const fn from_rgb(px: Pixel<3>, with_a: u8) -> Self { let mut i = 0; let mut out = Self::new(); while i < 3 { out.0[i] = px.0[i]; i += 1; } out.with_a(with_a) } #[inline] pub const fn from_array(arr: [u8; M]) -> Self { let mut i = 0; let mut out = Self::new(); while i < N && i < M { out.0[i] = arr[i]; i += 1; } out } #[inline] pub const fn r(self) -> u8 { self.0[0] } #[inline] pub const fn g(self) -> u8 { self.0[1] } #[inline] pub const fn b(self) -> u8 { self.0[2] } #[inline] pub const fn with_a(mut self, value: u8) -> Self { if N >= 4 { self.0[3] = value; } self } #[inline] pub const fn a_or(self, value: u8) -> u8 { if N < 4 { value } else { self.0[3] } } #[inline] pub const fn hash_index(self) -> u8 { let r = self.r().wrapping_mul(3); let g = self.g().wrapping_mul(5); let b = self.b().wrapping_mul(7); let a = self.a_or(0xff).wrapping_mul(11); r.wrapping_add(g).wrapping_add(b).wrapping_add(a) % 64 } #[inline] pub fn rgb_add(&mut self, r: u8, g: u8, b: u8) { self.0[0] = self.0[0].wrapping_add(r); self.0[1] = self.0[1].wrapping_add(g); self.0[2] = self.0[2].wrapping_add(b); } } impl From> for [u8; N] { #[inline(always)] fn from(px: Pixel) -> Self { px.0 } } pub trait SupportedChannels {} impl SupportedChannels for Pixel<3> {} impl SupportedChannels for Pixel<4> {}