mazeir/map/orthogonal/
image.rs1use std::error::Error;
2use std::fmt::{Display, Formatter};
3use std::io::Write;
4
5use png::{Encoder, BitDepth, ColorType};
6
7use super::{Orthogonal, LEFT_WALL, UP_WALL};
8use crate::output::Draw;
9
10
11impl Draw for Orthogonal {
12 type Error = DrawError;
13 fn draw<W: Write>(&self, writer: W) -> Result<(), Self::Error> {
14 let image_width = (self.width * 2 + 1) as u32;
15 let image_height = (self.height * 2 + 1) as u32;
16 let image_width_byte_count = (image_width as usize / 8) + if image_width % 8 == 0 { 0 } else { 1 };
17 let mut encoder = Encoder::new(writer, image_width, image_height);
18 encoder.set_depth(BitDepth::One);
19 encoder.set_color(ColorType::Indexed);
20 encoder.set_palette(vec![0, 0, 0, 255, 255, 255]);
21 let mut writer = encoder.write_header().map_err(|_| DrawError::WriteHeaderFailed)?;
22 let mut writer = writer.stream_writer_with_size(128 * 1024).map_err(|_| DrawError::CreateStreamWriterFailed)?;
23 if self.width == 0 || self.height == 0 {
24 writer.write(&[0b0]).map_err(|_| DrawError::StreamWriteFailed)?;
25 return Ok(());
26 }
27 for line in self.map.chunks(self.width) {
28 for cell in line.chunks(4) {
29 let mut byte = 0b0000_0000;
30 for (i, v) in cell.iter().enumerate() {
31 if *v & UP_WALL != 0 { byte |= 0b1 << (6 - i * 2); } }
33 writer.write(&[byte]).map_err(|_| DrawError::StreamWriteFailed)?;
34 }
35 if line.len() % 4 == 0 { writer.write(&[0b0]).map_err(|_| DrawError::StreamWriteFailed)?; }
36 for cell in line.chunks(4) {
37 let mut byte = 0b0101_0101;
38 for (i, v) in cell.iter().enumerate() {
39 if *v & LEFT_WALL != 0 { byte |= 0b1 << (7 - i * 2); } }
41 writer.write(&[byte]).map_err(|_| DrawError::StreamWriteFailed)?;
42 }
43 if line.len() % 4 == 0 { writer.write(&[0b0]).map_err(|_| DrawError::StreamWriteFailed)?; }
44 }
45 for _ in 0..image_width_byte_count { writer.write(&[0b0]).map_err(|_| DrawError::CreateStreamWriterFailed)?; }
46 Ok(())
47 }
48}
49
50#[derive(Debug)]
51pub enum DrawError {
52 WriteHeaderFailed,
53 CreateStreamWriterFailed,
54 StreamWriteFailed,
55
56}
57
58impl Display for DrawError {
59 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
60 match self {
61 DrawError::WriteHeaderFailed => write!(f, "Write header failed"),
62 DrawError::CreateStreamWriterFailed => write!(f, "Create stream writer failed"),
63 DrawError::StreamWriteFailed => write!(f, "Stream write failed"),
64 }
65 }
66}
67
68impl Error for DrawError {}