1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
use std::path::Path; use std::io::Write; use std::fs::File; const RGB_WIDTH: usize = 3; #[derive(Clone, Copy)] pub struct RGB { pub r: u8, pub g: u8, pub b: u8, pub a: u8 } pub struct Framebuffer { pub height: usize, pub width: usize, pub data: Vec<u8>, } impl Framebuffer { pub fn new(height: usize, width: usize) -> Framebuffer { let size = RGB_WIDTH * width * height; let buffer = vec![0; size as usize]; Framebuffer{ height: height, width: width, data: buffer, } } fn buffer_size(&self) -> usize { RGB_WIDTH * self.height * self.width } pub fn clear(&mut self, color: RGB) { let c: Vec<u8> = vec![ vec![color.r, color.g, color.b]; self.width * self.height ].into_iter().flatten().collect::<Vec<u8>>(); self.data = c; } fn get_offset(&self, x: usize, y: usize) -> Option<usize> { let offset = (y * self.width * RGB_WIDTH) + (x * RGB_WIDTH); if offset < self.buffer_size() { Some(offset as usize) } else { None } } pub fn get_pixel(&self, x: usize, y: usize) -> Option<RGB> { match self.get_offset(x, y) { Some(offset) => { let r = self.data[offset]; let g = self.data[offset + 1]; let b = self.data[offset + 2]; Some(RGB {r: r, g: g, b: b, a: 255}) }, None => None } } pub fn set_pixel(&mut self, x: usize, y: usize, color: RGB) -> bool { match self.get_offset(x, y) { Some(offset) => { self.data[offset] = color.r; self.data[offset + 1] = color.g; self.data[offset + 2] = color.b; true }, None => false } } pub fn draw_rect(&mut self, x: usize, y: usize, w: usize, h: usize, color: RGB) -> bool { let mut success = true; while success { for i in 0..w { for j in 0..h { let cx = x + i; let cy = y + j; if cx >= self.width || cy >= self.height { continue } success = self.set_pixel(cx, cy, color); } } break } success } pub fn write_file(&self, filename: &str) -> std::io::Result<()> { let path = Path::new(filename); let mut file = File::create(&path)?; let header = format!("P6 {} {} 255\n", self.width, self.height); file.write(header.as_bytes())?; file.write(&self.data)?; Ok(()) } }