1 use thiserror::Error;
2 #[derive(Debug, Error)]
3 pub enum NewFrameGeneratorError {
4     #[error("invalid stride")]
5     InvalidStride,
6 }
7 
8 #[derive(Debug, Error)]
9 pub enum GenerateFrameError {
10     #[error("provided buffer is too small")]
11     BufferTooSmall,
12 }
13 
14 pub struct FrameGenerator {
15     width: usize,
16     height: usize,
17     stride: usize,
18     step: u32,
19 }
20 
21 impl FrameGenerator {
new(width: usize, height: usize, stride: usize) -> Result<Self, NewFrameGeneratorError>22     pub fn new(width: usize, height: usize, stride: usize) -> Result<Self, NewFrameGeneratorError> {
23         if stride < width * 3 {
24             return Err(NewFrameGeneratorError::InvalidStride);
25         }
26 
27         Ok(FrameGenerator {
28             width,
29             height,
30             stride,
31             step: 0,
32         })
33     }
34 
frame_size(&self) -> usize35     pub fn frame_size(&self) -> usize {
36         self.stride * self.height
37     }
38 
next_frame<S: AsMut<[u8]>>(&mut self, frame: &mut S) -> Result<(), GenerateFrameError>39     pub fn next_frame<S: AsMut<[u8]>>(&mut self, frame: &mut S) -> Result<(), GenerateFrameError> {
40         let frame = frame.as_mut();
41 
42         if frame.len() < self.frame_size() {
43             return Err(GenerateFrameError::BufferTooSmall);
44         }
45 
46         self.gen_pattern(frame);
47         self.step = self.step.wrapping_add(1);
48 
49         Ok(())
50     }
51 
gen_pattern(&mut self, frame: &mut [u8])52     fn gen_pattern(&mut self, frame: &mut [u8]) {
53         frame
54             .chunks_exact_mut(self.stride)
55             .map(|l| &mut l[0..self.width * 3])
56             .enumerate()
57             .for_each(|(y, line)| {
58                 line.chunks_exact_mut(3).enumerate().for_each(|(x, pixel)| {
59                     let rgba = self.step.wrapping_add((x ^ y) as u32).to_le_bytes();
60                     pixel[0] = rgba[0];
61                     pixel[1] = rgba[1];
62                     pixel[2] = rgba[2];
63                 });
64             });
65     }
66 }
67