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