1use std::*;
6
7use std::marker::PhantomData;
8
9use crate::types::pixel::{PixelBW, PixelRGB24};
10
11pub trait Buff<Pixel> {
13 fn set(&mut self, x: usize, y: usize, p: &Pixel);
15 fn get(&self, x: usize, y: usize) -> Pixel;
17 fn size(&self) -> (usize, usize);
19 fn clear(&mut self, p: &Pixel);
21}
22
23#[derive(Debug)]
25pub struct Buffer<'a, Pixel> {
26 pub width: usize,
27 pub height: usize,
28 pub porch_bytes: usize,
29 pub trailer_bytes: usize,
30 pub line_width_bytes: usize,
31 pub data: &'a mut [u8],
32 _pixel: PhantomData<Pixel>,
33}
34
35impl <'a, Pixel> Buffer <'a, Pixel> {
36 pub fn data(&self) -> &[u8] {
37 self.data
38 }
39}
40
41impl <'a> Buffer <'a, PixelBW> {
42 pub fn new(width: usize, height: usize, porch_bytes: usize, trailer_bytes: usize, data: &'a mut [u8]) -> Self {
44 let line_width_bytes = porch_bytes + width / 8 + trailer_bytes;
45 return Self{width, height, porch_bytes, trailer_bytes, line_width_bytes, data, _pixel: PhantomData}
46 }
47}
48
49impl <'a> Buff<PixelBW> for Buffer <'a, PixelBW> {
50 fn set(&mut self, x: usize, y: usize, p: &PixelBW) {
52 let index = self.line_width_bytes * y + self.porch_bytes + x / 8;
53 let mask = 1 << (7 - x % 8) as u8;
54
55 if *p {
56 self.data[index as usize] |= mask;
57 } else {
58 self.data[index as usize] &= !mask;
59 }
60 }
61
62 fn get(&self, x: usize, y: usize) -> PixelBW {
64 let index = self.line_width_bytes * y + self.porch_bytes + x / 8;
65 let mask = 1 << (7 - x % 8);
66
67 if (self.data[index as usize] & mask) != 0 {
68 return true;
69 } else {
70 return false;
71 }
72 }
73
74 fn clear(&mut self, p: &PixelBW) {
76 for y in 0..self.height {
77 for x in 0..self.width {
78 self.set(x, y, p);
79 }
80 }
81 }
82
83 fn size(&self) -> (usize, usize) {
85 return (self.width, self.height);
86 }
87}
88
89impl <'a> Buffer <'a, PixelRGB24> {
90 pub fn new(width: usize, height: usize, porch_bytes: usize, trailer_bytes: usize, data: &'a mut [u8]) -> Self {
92 let line_width_bytes = porch_bytes + width * 3 + trailer_bytes;
93 return Self{width, height, porch_bytes, trailer_bytes, line_width_bytes, data, _pixel: PhantomData}
94 }
95}
96
97impl <'a> Buff<PixelRGB24> for Buffer <'a, PixelRGB24> {
98
99 fn set(&mut self, x: usize, y: usize, p: &PixelRGB24) {
101 let index: usize = self.line_width_bytes * y + x * 3 + self.porch_bytes;
102
103 self.data[index + 0] = p.r;
104 self.data[index + 1] = p.g;
105 self.data[index + 2] = p.b;
106 }
107
108 fn get(&self, x: usize, y: usize) -> PixelRGB24 {
110 let index: usize = self.line_width_bytes * y + x * 3 + self.porch_bytes;
111
112 return PixelRGB24{
113 r: self.data[index + 0],
114 g: self.data[index + 1],
115 b: self.data[index + 2]}
116 }
117
118 fn clear(&mut self, p: &PixelRGB24) {
120 for y in 0..self.height {
121 for x in 0..self.width {
122 self.set(x, y, p);
123 }
124 }
125 }
126
127 fn size(&self) -> (usize, usize) {
129 return (self.width, self.height);
130 }
131}
132
133
134impl <'a, Pixel>fmt::Display for Buffer<'a, Pixel> {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 write!(f, "[width: {}px height: {}px porch: {}B trailer: {}B line_width: {}B Data:\n",
138 self.width, self.height, self.porch_bytes, self.trailer_bytes, self.line_width_bytes).unwrap();
139 for l in 0..self.height {
140 let start: usize = l * self.line_width_bytes;
141 let end: usize = start + self.line_width_bytes - 1;
142 write!(f, "\t\t{:?}\n", &self.data[start..end]).unwrap();
143 }
144 write!(f, "\t]\n").unwrap();
145 Ok(())
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 use crate::types::pixel::*;
154
155 const WIDTH: usize = 16;
156 const HEIGHT: usize = 16;
157 const PORCH: usize = 1;
158 const TRAILER: usize = 1;
159 const SIZE_BW: usize = (PORCH + WIDTH / 8 + TRAILER) * HEIGHT;
160 const SIZE_RGB24: usize = (PORCH + WIDTH * 3 + TRAILER) * HEIGHT;
161
162 #[test]
163 fn test_bw() {
164 let mut data: [u8; SIZE_BW] = [0; SIZE_BW];
165 let data_slice = &mut data[..];
166 let mut buffer = Buffer::<PixelBW>::new(WIDTH, HEIGHT, PORCH, TRAILER, data_slice);
167
168 buffer.set(0, 0, &true);
169 assert_eq!(buffer.get(0, 0), true);
170 assert_eq!(buffer.data[PORCH], 0x80);
171
172 buffer.set(0, 0, &false);
173 assert_eq!(buffer.get(0, 0), false);
174 assert_eq!(buffer.data[PORCH], 0x00);
175
176 buffer.set(1, 1, &true);
177 assert_eq!(buffer.get(1, 1), true);
178 assert_eq!(buffer.data[PORCH + WIDTH / 8 + TRAILER + PORCH], 0x40);
179
180 buffer.set(1, 1, &false);
181 assert_eq!(buffer.get(1, 1), false);
182 assert_eq!(buffer.data[PORCH + WIDTH / 8 + TRAILER + PORCH], 0x00);
183 }
184
185 #[test]
186 fn test_rgb24_porch_trailer() {
187 let mut data: [u8; SIZE_RGB24] = [0; SIZE_RGB24];
188 let data_slice = &mut data[..];
189
190 let blank: [u8; SIZE_RGB24] = [0; SIZE_RGB24];
191 let blank_slice = &blank[..];
192
193 let mut buffer = Buffer::<PixelRGB24>::new(WIDTH, HEIGHT, PORCH, TRAILER, data_slice);
194
195 buffer.set(0, 0, &PixelRGB24::white());
196 assert_eq!(buffer.get(0, 0), PixelRGB24::white());
197 assert_eq!(buffer.data[PORCH + 0], 0xFF);
198 assert_eq!(buffer.data[PORCH + 1], 0xFF);
199 assert_eq!(buffer.data[PORCH + 2], 0xFF);
200
201 buffer.set(0, 0, &PixelRGB24::black());
202 assert_eq!(buffer.get(0, 0), PixelRGB24::black());
203 assert_eq!(buffer.data, blank_slice);
204
205 buffer.set(1, 1, &PixelRGB24::white());
206 assert_eq!(buffer.get(1, 1), PixelRGB24::white());
207
208 let index: usize = (PORCH + WIDTH * 3 + TRAILER) + 3 + PORCH;
209 assert_eq!(buffer.data[index + 0], 0xFF);
210 assert_eq!(buffer.data[index + 1], 0xFF);
211 assert_eq!(buffer.data[index + 2], 0xFF);
212
213 buffer.set(1, 1, &PixelRGB24::black());
214 assert_eq!(buffer.get(1, 1), PixelRGB24::black());
215 assert_eq!(buffer.data, blank_slice);
216 }
217
218 const X: usize = 2;
219 const Y: usize = 2;
220
221 #[test]
222 fn test_rgb24_buffer() {
223 let mut data = [0u8; X * Y * 3];
224
225 let mut buffer = Buffer::<PixelRGB24>::new(X, Y, 0, 0, &mut data);
226
227 let white = PixelRGB24::white();
228 let black = PixelRGB24::black();
229
230 for y in 0..Y {
231 for x in 0..X {
232 buffer.clear(&white);
233
234 buffer.set(x, y, &black);
235 assert_eq!(buffer.get(x, y), black);
236
237 let index = (y * Y + x) * 3;
238 assert_eq!(buffer.data[index+0], 0x00);
239 assert_eq!(buffer.data[index+1], 0x00);
240 assert_eq!(buffer.data[index+2], 0x00);
241 }
242 }
243 }
244}
245