use std::path::Path; use bmp::Pixel; use font8x8::{UnicodeFonts, BASIC_FONTS}; use crate::{interval::Interval, vec3::Color}; fn linear_to_gamma(linear_component: f64) -> f64 { if linear_component > 0.0 { return linear_component.sqrt(); } 0.0 } pub fn write_image>( path: P, image: &[Color], width: u32, height: u32, logs: &str, ) -> std::io::Result<()> { let per_pixel = (logs.len() / (width as usize * height as usize)).min(1); assert_ne!(per_pixel, 0); let mut out = bmp::Image::new(width * per_pixel as u32 * 8, height * per_pixel as u32 * 8); for y in 0..height { for x in 0..width { let index = (y as usize * width as usize) + x as usize; let r = linear_to_gamma(image[index as usize].r()); let g = linear_to_gamma(image[index as usize].g()); let b = linear_to_gamma(image[index as usize].b()); const INTENSITY: Interval = Interval::new(0.000, 0.999); let r = (INTENSITY.clamp(r) * 256.0) as u8; let g = (INTENSITY.clamp(g) * 256.0) as u8; let b = (INTENSITY.clamp(b) * 256.0) as u8; for y_sub in 0..per_pixel { for x_sub in 0..per_pixel { let y_idx = (y as usize + y_sub) * width as usize; let x_idx = x as usize + x_sub; let letter = logs.chars().nth(y_idx + x_idx).unwrap(); let letter_map = BASIC_FONTS.get(letter).unwrap(); for (char_row_idx, char_row) in letter_map.into_iter().enumerate() { for bit in 0..8 { let color = match char_row & 1 << bit { 0 => Pixel::new(0, 0, 0), _ => Pixel::new(r, g, b), }; out.set_pixel((x_idx as u32 * 8) + bit as u32, ((y as u32 + y_sub as u32) * 8) + char_row_idx as u32, color); } } } } } } out.save(path)?; Ok(()) }