1macro_rules! block_decoder {
6 ($name: ident, $block_width: expr, $block_height: expr, $raw_block_size: expr, $block_decode_func: expr) => {
7 pub fn $name(
9 data: &[u8],
10 width: usize,
11 height: usize,
12 image: &mut [u32],
13 ) -> Result<(), &'static str> {
14 const BLOCK_WIDTH: usize = $block_width;
15 const BLOCK_HEIGHT: usize = $block_height;
16 const BLOCK_SIZE: usize = BLOCK_WIDTH * BLOCK_HEIGHT;
17 let num_blocks_x: usize = (width + BLOCK_WIDTH - 1) / BLOCK_WIDTH;
18 let num_blocks_y: usize = (height + BLOCK_WIDTH - 1) / BLOCK_HEIGHT;
19 let mut buffer: [u32; BLOCK_SIZE] =
20 [crate::bcn::color::color(0, 0, 0, 255); BLOCK_SIZE];
21
22 if data.len() < num_blocks_x * num_blocks_y * $raw_block_size {
23 return Err("Not enough data to decode image!");
24 }
25
26 if image.len() < width * height {
27 return Err("Image buffer is too small!");
28 }
29
30 let mut data_offset = 0;
31 (0..num_blocks_y).for_each(|by| {
32 (0..num_blocks_x).for_each(|bx| {
33 $block_decode_func(&data[data_offset..], &mut buffer);
34 crate::bcn::color::copy_block_buffer(
35 bx,
36 by,
37 width,
38 height,
39 BLOCK_WIDTH,
40 BLOCK_HEIGHT,
41 &buffer,
42 image,
43 );
44 data_offset += $raw_block_size;
45 });
46 });
47 Ok(())
48 }
49 };
50}
51
52pub(crate) use block_decoder;