use std::fs::File; use std::io::Write; use crate::common::{DisplayBuffer, IMG_HEIGHT, IMG_WIDTH}; pub struct View<'a> { pub display_buffer: &'a DisplayBuffer, pub viewer: fn(&DisplayBuffer) -> Result, } impl<'a> View<'a> { pub fn display(&self) { let result = (self.viewer)(self.display_buffer); match result { Ok(success_msg) => { println!("{}", success_msg); }, Err(error_msg) => { eprintln!("{}", error_msg); } } } } pub mod render_viewer { use image::ImageFormat; use crate::common::Pixel; use super::*; pub fn ppm_exporter(data: &DisplayBuffer) -> 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 common_img_format_exporter(data: &DisplayBuffer, img_format: ImageFormat) -> Result { let ext = match img_format { ImageFormat::Png => { "png" } ImageFormat::Jpeg => { "jpeg" } ImageFormat::Bmp => { "bmp" } _ => { return Err(std::io::Error::new(std::io::ErrorKind::Other, "Not supported")); } }; let file_name = format!("output.{}", ext); let mut imgbuf = image::ImageBuffer::new(IMG_WIDTH as u32, IMG_HEIGHT as u32); for (x, y, pixel) in imgbuf.enumerate_pixels_mut() { let Pixel{r, g, b} = data[y as usize][x as usize]; *pixel = image::Rgb([r, g, b]); } imgbuf.save(file_name.clone()).unwrap(); Ok(format!("Output rendered to file {}", file_name)) } pub fn png_exporter(data: &DisplayBuffer) -> Result { common_img_format_exporter(data, ImageFormat::Png) } pub fn jpeg_exporter(data: &DisplayBuffer) -> Result { common_img_format_exporter(data, ImageFormat::Jpeg) } pub fn bmp_exporter(data: &DisplayBuffer) -> Result { common_img_format_exporter(data, ImageFormat::Bmp) } }