use bitvec::{field::BitField, order::Lsb0, view::BitView}; trait Sealed {} #[derive(Clone, PartialEq, Debug, Default)] pub struct Mask(std::ops::Range); impl Mask { const fn empty() -> Self { Self(0..0) } const fn select_byte(index: usize) -> Self { Self((index * 8)..(index * 8 + 8)) } } /* #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, enum_map::Enum)] pub enum DynamicPixelFormat { A8, Abgr32, Bgr24, Bgr32, Rgb24, Rgb32, Rgba32, } macro_rules! masks_for { ($n:ident) => { ($n::RED_MASK, $n::GREEN_MASK, $n::BLUE_MASK, $n::ALPHA_MASK) } } impl DynamicPixelFormat { pub fn pixel_width(&self) -> usize { match self { Self::A8 => A8::PIXEL_WIDTH, Self::Bgr24 => Bgr24::PIXEL_WIDTH, Self::Bgr32 => Bgr32::PIXEL_WIDTH, Self::Abgr32 => Abgr32::PIXEL_WIDTH, Self::Rgb24 => Rgb24::PIXEL_WIDTH, Self::Rgb32 => Rgb32::PIXEL_WIDTH, Self::Rgba32 => Rgba32::PIXEL_WIDTH, } } pub const fn masks(&self) -> (Mask, Mask, Mask, Mask) { match self { Self::A8 => masks_for!(A8), Self::Abgr32 => masks_for!(Abgr32), Self::Bgr24 => masks_for!(Bgr24), Self::Bgr32 => masks_for!(Bgr32), Self::Rgb24 => masks_for!(Rgb24), Self::Rgb32 => masks_for!(Rgb32), Self::Rgba32 => masks_for!(Rgba32), } } pub fn red_mask(&self) -> Mask { self.masks().0 } pub fn green_mask(&self) -> Mask { self.masks().1 } pub fn blue_mask(&self) -> Mask { self.masks().2 } pub fn alpha_mask(&self) -> Mask { self.masks().3 } /*pub fn write_colour(&self, c: Colour, to: &mut [u8]) { let bits = to.view_bits_mut::(); bits[self.masks().0.0].store_be::(c.r); bits[self.masks().1.0].store_be::(c.g); bits[self.masks().2.0].store_be::(c.b); bits[self.masks().3.0].store_be::(c.a); }*/ } */ #[allow(private_bounds)] pub trait PixelFormat: Sealed + Clone + Copy { const CHANNELS: usize; const PIXEL_WIDTH: usize; const NAME: &'static str; const RED_MASK: Mask; const GREEN_MASK: Mask; const BLUE_MASK: Mask; const ALPHA_MASK: Mask; } //----------------------------------------------------------------------------- // Pixel formats //----------------------------------------------------------------------------- /// 8-bit alpha map #[derive(Clone, Copy, PartialEq)] pub struct A8; impl Sealed for A8 {} impl PixelFormat for A8 { const CHANNELS: usize = 1; const PIXEL_WIDTH: usize = 1; const NAME: &'static str = "A8"; const RED_MASK: Mask = Mask::empty(); const GREEN_MASK: Mask = Mask::empty(); const BLUE_MASK: Mask = Mask::empty(); const ALPHA_MASK: Mask = Mask::select_byte(0); } /// RGBA with 8 bits per channel, stored big-endian /// /// This assumes the following memory layout: /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// A | B | G | R | A | B | G | R | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Abgr32; impl Sealed for Abgr32 {} impl PixelFormat for Abgr32 { const CHANNELS: usize = 4; const PIXEL_WIDTH: usize = 4; const NAME: &'static str = "Abgr32"; const RED_MASK: Mask = Mask::select_byte(3); const GREEN_MASK: Mask = Mask::select_byte(2); const BLUE_MASK: Mask = Mask::select_byte(1); const ALPHA_MASK: Mask = Mask::select_byte(0); } /// 24bpp colour densly packed into 24-bit words /// /// This assumes the following memory layout: /// /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// R | G | B | R | G | B | R | G | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Bgr24; impl Sealed for Bgr24 {} impl PixelFormat for Bgr24 { const CHANNELS: usize = 3; const PIXEL_WIDTH: usize = 3; const NAME: &'static str = "Bgr24"; const RED_MASK: Mask = Mask::select_byte(0); const GREEN_MASK: Mask = Mask::select_byte(1); const BLUE_MASK: Mask = Mask::select_byte(2); const ALPHA_MASK: Mask = Mask::empty(); } /// 24bpp colour packed into 32-bit words /// /// This assumes the following memory layout: /// /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// R | G | B | - | R | G | B | - | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Bgr32; impl Sealed for Bgr32 {} impl PixelFormat for Bgr32 { const CHANNELS: usize = 3; const PIXEL_WIDTH: usize = 4; const NAME: &'static str = "Bgr32"; const RED_MASK: Mask = Mask::select_byte(2); const GREEN_MASK: Mask = Mask::select_byte(1); const BLUE_MASK: Mask = Mask::select_byte(0); const ALPHA_MASK: Mask = Mask::empty(); } /// 24bpp colour densly packed into 24-bit words /// /// This assumes the following memory layout: /// /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// B | G | R | B | G | R | B | G | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Rgb24; impl Sealed for Rgb24 {} impl PixelFormat for Rgb24 { const CHANNELS: usize = 3; const PIXEL_WIDTH: usize = 3; const NAME: &'static str = "Rgb24"; const RED_MASK: Mask = Mask::select_byte(2); const GREEN_MASK: Mask = Mask::select_byte(1); const BLUE_MASK: Mask = Mask::select_byte(0); const ALPHA_MASK: Mask = Mask::empty(); } /// 24bpp colour packed into 32-bit words /// /// This assumes the following memory layout: /// /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// B | G | R | - | B | G | R | - | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Rgb32; impl Sealed for Rgb32 {} impl PixelFormat for Rgb32 { const CHANNELS: usize = 3; const PIXEL_WIDTH: usize = 4; const NAME: &'static str = "Rgb32"; const RED_MASK: Mask = Mask::select_byte(2); const GREEN_MASK: Mask = Mask::select_byte(1); const BLUE_MASK: Mask = Mask::select_byte(0); const ALPHA_MASK: Mask = Mask::empty(); } /// RGBA with 8 bits per channel, stored little-endian /// /// This assumes the following memory layout: /// ```text /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ... /// ---+---+---+---+---+---+---+---+--- /// R | G | B | A | R | G | B | A | ... /// ``` #[derive(Clone, Copy, PartialEq)] pub struct Rgba32; impl Sealed for Rgba32 {} impl PixelFormat for Rgba32 { const CHANNELS: usize = 4; const PIXEL_WIDTH: usize = 4; const NAME: &'static str = "Rgba32"; const RED_MASK: Mask = Mask::select_byte(0); const GREEN_MASK: Mask = Mask::select_byte(1); const BLUE_MASK: Mask = Mask::select_byte(2); const ALPHA_MASK: Mask = Mask::select_byte(3); }