1use crate::pixel::PixelColor;
2use std::{fmt, io::Read};
3const TIF_HEADER: [u8;5] = [46, 84, 73, 70, 32];
4
5#[derive(Debug)]
6pub enum TifImageError {
7 InvalidHeader
8}
9
10impl fmt::Display for TifImageError {
11 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12 write!(f, "{:?}", self)
13 }
14}
15
16impl std::error::Error for TifImageError{}
17
18#[derive(Clone, Debug)]
19pub struct TifImage {
20 pub height: u64, pub width: u8,
22 pub pixels: Vec<Vec<PixelColor>>
23}
24
25impl TifImage {
26 pub fn parse_from_file(filename: String) -> Result<Self, Box<dyn std::error::Error>> {
27 let mut file = std::fs::File::open(filename)?;
28 let mut buf: Vec<u8> = Vec::with_capacity(1024);
29 file.read_to_end(&mut buf)?;
30 Self::parse_from_bytes(buf)
31 }
32
33 pub fn parse_from_bytes(bytes: Vec<u8>) -> Result<Self, Box<dyn std::error::Error>> {
34 if bytes[0..5] != TIF_HEADER {
35 return Err(Box::new(TifImageError::InvalidHeader));
36 }
37 let width: u8 = bytes[5];
39
40
41 let mut raw_pixels: Vec<PixelColor> = vec![];
42
43 for byte in bytes[6..].chunks(2) {
44 if byte[1] == 0 { continue; }
45 for _ in 0..byte[1] {
46 raw_pixels.push(PixelColor::from(byte[0]));
47 }
48 }
49
50 let height = (raw_pixels.len() as u64) / (width as u64);
52
53 let pixels: Vec<Vec<PixelColor>> = raw_pixels.chunks(width as usize).map(|pixel| {
54 pixel.to_vec()
55 }).collect::<Vec<Vec<PixelColor>>>();
56
57 Ok(Self {
58 height,
59 width,
60 pixels
61 })
62 }
63
64 pub fn save(&self) -> Vec<u8> {
65 let mut buf: Vec<u8> = vec![];
66 buf.extend(TIF_HEADER.iter());
67 buf.push(self.width);
68 let mut current_color = PixelColor::Black;
69 let mut pixels: u8 = 0;
70
71 for i in &self.pixels {
72 for px in i {
73
74
75 if *px == current_color {
76 pixels += 1;
77 if pixels >= 255 {
78 buf.push((*px).into());
79 buf.push(pixels);
80 pixels = 0;
81 }
82 }else {
83 if pixels > 0 {
84 buf.push(current_color.into());
85 buf.push(pixels);
86 }
87 current_color = *px;
88 pixels = 1;
89 }
90 }
91 }
92
93 if pixels > 0 {
94 buf.push(current_color.into());
95 buf.push(pixels);
96 }
97
98 buf
99 }
100
101}