123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- use bitvec::{field::BitField, order::Lsb0, view::BitView};
- trait Sealed {}
- #[derive(Clone, PartialEq, Debug, Default)]
- pub struct Mask(std::ops::Range<usize>);
- 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::<Lsb0>();
- bits[self.masks().0.0].store_be::<u8>(c.r);
- bits[self.masks().1.0].store_be::<u8>(c.g);
- bits[self.masks().2.0].store_be::<u8>(c.b);
- bits[self.masks().3.0].store_be::<u8>(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);
- }
|