use pizzicato::{ Context, ImageBuffer, PixelFormat, Options }; use anyhow::Result; use noise::{ NoiseFn, Perlin, Seedable }; use rand::random; #[derive(Clone, Copy, Debug)] struct NoiseVideo { size: (u32, u32), length: u32, spread: f64, t: u32, source: Perlin, } impl NoiseVideo { fn new(size: (u32, u32), length: u32, spread: f64) -> Self { Self { size, length, spread, t: 0, source: Perlin::new() .set_seed(random()), } } } impl Iterator for NoiseVideo { type Item = ImageBuffer; fn next(&mut self) -> Option { if self.t >= self.length { return None } let mut data = Vec::with_capacity( (self.size.0 * self.size.1 * 3) as usize ); let xg = self.spread / self.size.0 as f64; let yg = self.spread / self.size.1 as f64; let tg = self.spread / self.length as f64; for y in 0..self.size.1 { for x in 0..self.size.0 { let value = self.source.get([ xg * x as f64, yg * y as f64, tg * self.t as f64, ]) * 255f64; for _ in 0..3 { data.push(value as u8); } } } // to profile without `noise` overhead, use this // data.resize(data.capacity(), 0x7fu8); self.t += 1; Some(ImageBuffer { size: self.size, data, pix_fmt: PixelFormat::Rgb8, }) } } #[test] fn noise_test() -> Result<()> { const SIZE: (u32, u32) = (640, 360); const FPS: i32 = 30; std::fs::create_dir_all("temp")?; let file = format!("temp/test-{:04x}.mp4", random::()); let mut ctx = Context::create(&file)?; let generator = NoiseVideo::new(SIZE, FPS as u32 * 10, 10f64); ctx.video(generator, Options { size: SIZE, frame_rate: FPS, pix_fmt: PixelFormat::Rgb8, bit_rate: None, gop_size: None, max_b_frames: None, })?; println!("Output to {}", file); Ok(()) }