1use const_default::ConstDefault;
2use std::fmt::Display;
3
4#[derive(Debug, Clone, Copy)]
5pub struct Pixel {
7 pub r: u8,
9 pub g: u8,
11 pub b: u8,
13}
14
15impl ConstDefault for Pixel {
16 const DEFAULT: Pixel = Pixel::new(0, 0, 0);
18}
19
20impl Display for Pixel {
21 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22 write!(f, "{}\t{}\t{}", self.r, self.g, self.b)
23 }
24}
25
26pub struct Ppm<const W: usize, const H: usize> {
28 rows: Vec<Vec<Pixel>>,
29}
30
31impl Pixel {
32 pub const fn new(r: u8, g: u8, b: u8) -> Self {
34 Self { r, g, b }
35 }
36}
37
38impl<const W: usize, const H: usize> Ppm<W, H> {
39 pub fn new(rows: Vec<Vec<Pixel>>) -> Self {
43 assert_eq!(rows.len(), H);
44 for row in rows.iter() {
45 assert_eq!(row.len(), W);
46 }
47
48 unsafe { Self::new_unchecked(rows) }
49 }
50
51 pub unsafe fn new_unchecked(rows: Vec<Vec<Pixel>>) -> Self {
58 Self { rows }
59 }
60
61 pub fn gen<F>(f: F) -> Self
65 where
66 F: Fn(usize, usize) -> Pixel,
67 {
68 let mut rows = Vec::<Vec<Pixel>>::with_capacity(H);
69 for y in 0..H {
70 let mut row_data = Vec::<Pixel>::with_capacity(W);
71 for x in 0..W {
72 row_data.push(f(x, y));
73 }
74 rows.push(row_data);
75 }
76
77 unsafe { Self::new_unchecked(rows) }
78 }
79}
80
81impl<const W: usize, const H: usize> Display for Ppm<W, H> {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 writeln!(f, "P3")?;
84 writeln!(f, "{}\t{}", W, H)?;
85 writeln!(f, "255")?;
86 for row in self.rows.iter() {
87 for pixel in row.iter() {
88 writeln!(f, "{}", pixel)?;
89 }
90 }
91
92 Ok(())
93 }
94}
95
96impl IntoIterator for Pixel {
97 type Item = u8;
98 type IntoIter = std::array::IntoIter<u8, 3>;
99
100 fn into_iter(self) -> Self::IntoIter {
101 [self.r, self.g, self.b].into_iter()
102 }
103}