embedded_sprites/
image.rs1use core::{
2 fmt,
3 fmt::{Debug, Display, Formatter},
4};
5use embedded_graphics::pixelcolor::PixelColor;
6
7#[derive(Debug)]
12pub struct Image<'a, C: PixelColor> {
13 pub(crate) width: u16,
14 pub(crate) transparenty: &'a [u8],
15 pub(crate) colors: &'a [C],
16}
17
18#[derive(Debug, Eq, PartialEq)]
19pub enum Dimension {
20 Width,
21 Height,
22}
23
24#[derive(Debug, Eq, PartialEq)]
25pub enum Error {
26 WrongPixelLength(Dimension),
27}
28
29impl Display for Error {
30 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
31 match self {
32 Self::WrongPixelLength(dimension) => match dimension {
33 Dimension::Width => write!(f, "length of `colors` is is not divisible by `width`"),
34 Dimension::Height => write!(f, "`colors.len()/width` does not match provided `height`"),
35 },
36 }
37 }
38}
39impl Error {
40 #[doc(hidden)]
41 pub const fn panic(&self) -> ! {
43 match self {
44 Self::WrongPixelLength(dimension) => match dimension {
45 Dimension::Width => panic!("Error creating image: length of `colors` is is not divisible by `width`"),
46 Dimension::Height => panic!("Error creating image: `colors.len()/width` does not match provided `height`"),
47 },
48 }
49 }
50}
51
52impl<'a, C: PixelColor> Image<'a, C> {
53 pub const fn new(colors: &'a [C], transparenty: &'a [u8], width: u16, height: u16) -> Result<Self, Error> {
81 if colors.len() % width as usize != 0 {
82 return Err(Error::WrongPixelLength(Dimension::Width));
83 };
84 if colors.len() / width as usize != height as usize {
85 return Err(Error::WrongPixelLength(Dimension::Height));
86 };
87 Ok(Image {
88 colors,
89 transparenty,
90 width,
91 })
92 }
93}
94
95#[macro_export]
106macro_rules! transparency {
107 ($($x:expr),*) => {
108 {
109 const N: usize = [$($x),*].len();
110 const LEN: usize = N / 8 + if N % 8 > 0 { 1 } else { 0 };
111 const T: [u8; LEN] = {
112 let mut t = [0u8; LEN];
113 let mut i = 0;
114 let mut j = 7;
115 $(
116 t[i] |= ($x & 1 ) << j;
117 #[allow(unused_assignments)]
118 if j == 0 {
119 j = 7;
120 i += 1;
121 } else {
122 j -= 1;
123 }
124 )*
125 t
126 };
127 T
128 }
129 };
130}
131
132#[cfg(test)]
133mod tests {
134 use super::{Dimension, Error, Image};
135 use crate::transparency;
136 use embedded_graphics::pixelcolor::Bgr565;
137 use konst::result::unwrap_ctx;
138
139 type Color = Bgr565;
140
141 const IMAGE_DATA: [Color; 6] = [
142 Color::new(255, 0, 0),
143 Color::new(0, 255, 0),
144 Color::new(0, 0, 255),
145 Color::new(255, 0, 255),
146 Color::new(255, 255, 255),
147 Color::new(255, 255, 255),
148 ];
149
150 #[test]
151 fn create_const_image() {
152 #[allow(dead_code)]
153 const IMAGE1: Image<Color> = unwrap_ctx!(Image::new(&IMAGE_DATA, &transparency![0, 0, 0, 1, 0, 0], 3, 2));
154 #[allow(dead_code)]
155 const IMAGE2: Image<Color> = unwrap_ctx!(Image::new(&IMAGE_DATA, &transparency![0, 0, 0, 0], 3, 2));
156 }
158 #[test]
159 fn create_image_wrong_widht() {
160 assert_eq!(
161 Image::new(&IMAGE_DATA, &transparency![0, 0, 0, 0], 4, 2).unwrap_err(),
162 Error::WrongPixelLength(Dimension::Width)
163 );
164 }
165 #[test]
166 fn create_image_wrong_hight() {
167 assert_eq!(
168 Image::new(&IMAGE_DATA, &transparency![0, 0, 0, 0], 3, 3).unwrap_err(),
169 Error::WrongPixelLength(Dimension::Height)
170 );
171 }
172}