1use orfail::OrFail;
2use pati::{Color, Point};
3use std::{collections::BTreeMap, io::Write};
4
5pub fn write_image<W: Write>(
6 mut writer: W,
7 width: u16,
8 height: u16,
9 pixels: impl Iterator<Item = (Point, Color)>,
10) -> orfail::Result<()> {
11 let image_data_offset: u32 = 54;
12 let num_of_pixels = width as u32 * height as u32;
13 let file_size: u32 = image_data_offset + num_of_pixels * 4;
14
15 writer.write_all(b"BM").or_fail()?;
17 writer.write_all(&file_size.to_le_bytes()).or_fail()?;
18 writer.write_all(&[0, 0, 0, 0]).or_fail()?;
19 writer
20 .write_all(&image_data_offset.to_le_bytes())
21 .or_fail()?;
22
23 writer.write_all(&[40, 0, 0, 0]).or_fail()?; writer.write_all(&(width as i32).to_le_bytes()).or_fail()?;
26 writer.write_all(&(height as i32).to_le_bytes()).or_fail()?;
27 writer.write_all(&[1, 0]).or_fail()?; writer.write_all(&[32, 0]).or_fail()?; writer.write_all(&[0, 0, 0, 0]).or_fail()?; writer
31 .write_all(&(num_of_pixels * 4).to_le_bytes())
32 .or_fail()?; writer.write_all(&[0, 0, 0, 0]).or_fail()?; writer.write_all(&[0, 0, 0, 0]).or_fail()?; writer.write_all(&[0, 0, 0, 0]).or_fail()?; writer.write_all(&[0, 0, 0, 0]).or_fail()?; let pixels = pixels.collect::<BTreeMap<_, _>>();
40 for y in 0..height {
41 for x in 0..width {
42 let c = pixels
43 .get(&Point::new(x as i16, y as i16))
44 .copied()
45 .unwrap_or(Color::rgba(255, 255, 255, 0));
46 writer.write_all(&[c.b, c.g, c.r, c.a]).or_fail()?;
47 }
48 }
49 Ok(())
50}