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