use std::fs::File; use std::io::Write; const IMG_WIDTH: usize = 256; const IMG_HEIGHT: usize = 256; #[derive(Debug, Copy, Clone)] struct Pixel { r: u8, g: u8, b: u8, } impl Default for Pixel { fn default() -> Self { Pixel { r:0, g:0, b:0 } } } struct View<'a> { data: &'a[[Pixel; IMG_WIDTH]; IMG_HEIGHT], renderer: fn(&[[Pixel; IMG_WIDTH]; IMG_HEIGHT]) -> Result, } impl<'a> View<'a> { fn render(&self) { let result = (self.renderer)(self.data); match result { Ok(success_msg) => { println!("{}", success_msg); }, Err(error_msg) => { eprintln!("{}", error_msg); } } } } fn ppm_renderer(data: &[[Pixel; IMG_WIDTH]; IMG_HEIGHT]) -> Result { let file_name = "output.ppm"; let mut file = File::create(file_name)?; // header let mut txt_data = String::from("P3\n"); txt_data.push_str(format!("{} {}\n255\n", IMG_WIDTH, IMG_HEIGHT).as_str()); // data point data.iter().for_each(|row| { row.iter().for_each(|&pixel| { txt_data.push_str(&format!("{} {} {}\n", pixel.r, pixel.g, pixel.b)); }) }); file.write_all(txt_data.as_bytes())?; Ok(format!("Output rendered to file {}", file_name)) } fn main() { let mut data = [[Pixel::default(); IMG_WIDTH]; IMG_HEIGHT]; (0..IMG_HEIGHT).for_each(|j| { (0..IMG_WIDTH).for_each(|i| { let r = i as f32 / IMG_WIDTH as f32; let g = j as f32 / IMG_HEIGHT as f32; let b = 0.0f32; let ir = (255.999 * r) as u8; let ig = (255.999 * g) as u8; let ib = (255.999 * b) as u8; data[i][j] = Pixel { r: ir, g: ig, b: ib}; }) }); let view = View { data: &data, renderer: ppm_renderer, }; view.render(); }