formats.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. use bitvec::{field::BitField, order::Lsb0, view::BitView};
  2. trait Sealed {}
  3. #[derive(Clone, PartialEq, Debug, Default)]
  4. pub struct Mask(std::ops::Range<usize>);
  5. impl Mask {
  6. const fn empty() -> Self {
  7. Self(0..0)
  8. }
  9. const fn select_byte(index: usize) -> Self {
  10. Self((index * 8)..(index * 8 + 8))
  11. }
  12. }
  13. /*
  14. #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, enum_map::Enum)]
  15. pub enum DynamicPixelFormat {
  16. A8,
  17. Abgr32,
  18. Bgr24,
  19. Bgr32,
  20. Rgb24,
  21. Rgb32,
  22. Rgba32,
  23. }
  24. macro_rules! masks_for {
  25. ($n:ident) => {
  26. ($n::RED_MASK, $n::GREEN_MASK, $n::BLUE_MASK, $n::ALPHA_MASK)
  27. }
  28. }
  29. impl DynamicPixelFormat {
  30. pub fn pixel_width(&self) -> usize {
  31. match self {
  32. Self::A8 => A8::PIXEL_WIDTH,
  33. Self::Bgr24 => Bgr24::PIXEL_WIDTH,
  34. Self::Bgr32 => Bgr32::PIXEL_WIDTH,
  35. Self::Abgr32 => Abgr32::PIXEL_WIDTH,
  36. Self::Rgb24 => Rgb24::PIXEL_WIDTH,
  37. Self::Rgb32 => Rgb32::PIXEL_WIDTH,
  38. Self::Rgba32 => Rgba32::PIXEL_WIDTH,
  39. }
  40. }
  41. pub const fn masks(&self) -> (Mask, Mask, Mask, Mask) {
  42. match self {
  43. Self::A8 => masks_for!(A8),
  44. Self::Abgr32 => masks_for!(Abgr32),
  45. Self::Bgr24 => masks_for!(Bgr24),
  46. Self::Bgr32 => masks_for!(Bgr32),
  47. Self::Rgb24 => masks_for!(Rgb24),
  48. Self::Rgb32 => masks_for!(Rgb32),
  49. Self::Rgba32 => masks_for!(Rgba32),
  50. }
  51. }
  52. pub fn red_mask(&self) -> Mask {
  53. self.masks().0
  54. }
  55. pub fn green_mask(&self) -> Mask {
  56. self.masks().1
  57. }
  58. pub fn blue_mask(&self) -> Mask {
  59. self.masks().2
  60. }
  61. pub fn alpha_mask(&self) -> Mask {
  62. self.masks().3
  63. }
  64. /*pub fn write_colour(&self, c: Colour, to: &mut [u8]) {
  65. let bits = to.view_bits_mut::<Lsb0>();
  66. bits[self.masks().0.0].store_be::<u8>(c.r);
  67. bits[self.masks().1.0].store_be::<u8>(c.g);
  68. bits[self.masks().2.0].store_be::<u8>(c.b);
  69. bits[self.masks().3.0].store_be::<u8>(c.a);
  70. }*/
  71. }
  72. */
  73. #[allow(private_bounds)]
  74. pub trait PixelFormat: Sealed + Clone + Copy {
  75. const CHANNELS: usize;
  76. const PIXEL_WIDTH: usize;
  77. const NAME: &'static str;
  78. const RED_MASK: Mask;
  79. const GREEN_MASK: Mask;
  80. const BLUE_MASK: Mask;
  81. const ALPHA_MASK: Mask;
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Pixel formats
  85. //-----------------------------------------------------------------------------
  86. /// 8-bit alpha map
  87. #[derive(Clone, Copy, PartialEq)]
  88. pub struct A8;
  89. impl Sealed for A8 {}
  90. impl PixelFormat for A8 {
  91. const CHANNELS: usize = 1;
  92. const PIXEL_WIDTH: usize = 1;
  93. const NAME: &'static str = "A8";
  94. const RED_MASK: Mask = Mask::empty();
  95. const GREEN_MASK: Mask = Mask::empty();
  96. const BLUE_MASK: Mask = Mask::empty();
  97. const ALPHA_MASK: Mask = Mask::select_byte(0);
  98. }
  99. /// RGBA with 8 bits per channel, stored big-endian
  100. ///
  101. /// This assumes the following memory layout:
  102. /// ```text
  103. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  104. /// ---+---+---+---+---+---+---+---+---
  105. /// A | B | G | R | A | B | G | R | ...
  106. /// ```
  107. #[derive(Clone, Copy, PartialEq)]
  108. pub struct Abgr32;
  109. impl Sealed for Abgr32 {}
  110. impl PixelFormat for Abgr32 {
  111. const CHANNELS: usize = 4;
  112. const PIXEL_WIDTH: usize = 4;
  113. const NAME: &'static str = "Abgr32";
  114. const RED_MASK: Mask = Mask::select_byte(3);
  115. const GREEN_MASK: Mask = Mask::select_byte(2);
  116. const BLUE_MASK: Mask = Mask::select_byte(1);
  117. const ALPHA_MASK: Mask = Mask::select_byte(0);
  118. }
  119. /// 24bpp colour densly packed into 24-bit words
  120. ///
  121. /// This assumes the following memory layout:
  122. ///
  123. /// ```text
  124. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  125. /// ---+---+---+---+---+---+---+---+---
  126. /// R | G | B | R | G | B | R | G | ...
  127. /// ```
  128. #[derive(Clone, Copy, PartialEq)]
  129. pub struct Bgr24;
  130. impl Sealed for Bgr24 {}
  131. impl PixelFormat for Bgr24 {
  132. const CHANNELS: usize = 3;
  133. const PIXEL_WIDTH: usize = 3;
  134. const NAME: &'static str = "Bgr24";
  135. const RED_MASK: Mask = Mask::select_byte(0);
  136. const GREEN_MASK: Mask = Mask::select_byte(1);
  137. const BLUE_MASK: Mask = Mask::select_byte(2);
  138. const ALPHA_MASK: Mask = Mask::empty();
  139. }
  140. /// 24bpp colour packed into 32-bit words
  141. ///
  142. /// This assumes the following memory layout:
  143. ///
  144. /// ```text
  145. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  146. /// ---+---+---+---+---+---+---+---+---
  147. /// R | G | B | - | R | G | B | - | ...
  148. /// ```
  149. #[derive(Clone, Copy, PartialEq)]
  150. pub struct Bgr32;
  151. impl Sealed for Bgr32 {}
  152. impl PixelFormat for Bgr32 {
  153. const CHANNELS: usize = 3;
  154. const PIXEL_WIDTH: usize = 4;
  155. const NAME: &'static str = "Bgr32";
  156. const RED_MASK: Mask = Mask::select_byte(2);
  157. const GREEN_MASK: Mask = Mask::select_byte(1);
  158. const BLUE_MASK: Mask = Mask::select_byte(0);
  159. const ALPHA_MASK: Mask = Mask::empty();
  160. }
  161. /// 24bpp colour densly packed into 24-bit words
  162. ///
  163. /// This assumes the following memory layout:
  164. ///
  165. /// ```text
  166. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  167. /// ---+---+---+---+---+---+---+---+---
  168. /// B | G | R | B | G | R | B | G | ...
  169. /// ```
  170. #[derive(Clone, Copy, PartialEq)]
  171. pub struct Rgb24;
  172. impl Sealed for Rgb24 {}
  173. impl PixelFormat for Rgb24 {
  174. const CHANNELS: usize = 3;
  175. const PIXEL_WIDTH: usize = 3;
  176. const NAME: &'static str = "Rgb24";
  177. const RED_MASK: Mask = Mask::select_byte(2);
  178. const GREEN_MASK: Mask = Mask::select_byte(1);
  179. const BLUE_MASK: Mask = Mask::select_byte(0);
  180. const ALPHA_MASK: Mask = Mask::empty();
  181. }
  182. /// 24bpp colour packed into 32-bit words
  183. ///
  184. /// This assumes the following memory layout:
  185. ///
  186. /// ```text
  187. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  188. /// ---+---+---+---+---+---+---+---+---
  189. /// B | G | R | - | B | G | R | - | ...
  190. /// ```
  191. #[derive(Clone, Copy, PartialEq)]
  192. pub struct Rgb32;
  193. impl Sealed for Rgb32 {}
  194. impl PixelFormat for Rgb32 {
  195. const CHANNELS: usize = 3;
  196. const PIXEL_WIDTH: usize = 4;
  197. const NAME: &'static str = "Rgb32";
  198. const RED_MASK: Mask = Mask::select_byte(2);
  199. const GREEN_MASK: Mask = Mask::select_byte(1);
  200. const BLUE_MASK: Mask = Mask::select_byte(0);
  201. const ALPHA_MASK: Mask = Mask::empty();
  202. }
  203. /// RGBA with 8 bits per channel, stored little-endian
  204. ///
  205. /// This assumes the following memory layout:
  206. /// ```text
  207. /// 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | ...
  208. /// ---+---+---+---+---+---+---+---+---
  209. /// R | G | B | A | R | G | B | A | ...
  210. /// ```
  211. #[derive(Clone, Copy, PartialEq)]
  212. pub struct Rgba32;
  213. impl Sealed for Rgba32 {}
  214. impl PixelFormat for Rgba32 {
  215. const CHANNELS: usize = 4;
  216. const PIXEL_WIDTH: usize = 4;
  217. const NAME: &'static str = "Rgba32";
  218. const RED_MASK: Mask = Mask::select_byte(0);
  219. const GREEN_MASK: Mask = Mask::select_byte(1);
  220. const BLUE_MASK: Mask = Mask::select_byte(2);
  221. const ALPHA_MASK: Mask = Mask::select_byte(3);
  222. }