A photo manager for VRChat.
1use serde::ser::{Serialize, SerializeStruct, Serializer};
2use std::str;
3
4#[derive(Clone)]
5pub struct PNGImage {
6 width: u32,
7 height: u32,
8 bit_depth: u8,
9 colour_type: u8,
10 compression_method: u8,
11 filter_method: u8,
12 interlace_method: u8,
13 metadata: String,
14 path: String,
15}
16
17impl PNGImage {
18 pub fn new(buff: Vec<u8>, path: String) -> PNGImage {
19 if buff[0] != 0x89
20 || buff[1] != 0x50
21 || buff[2] != 0x4E
22 || buff[3] != 0x47
23 || buff[4] != 0x0D
24 || buff[5] != 0x0A
25 || buff[6] != 0x1A
26 || buff[7] != 0x0A
27 {
28 dbg!(path);
29 panic!("Image is not a PNG file");
30 }
31
32 let mut img = PNGImage {
33 width: 0,
34 height: 0,
35 bit_depth: 0,
36 colour_type: 0,
37 compression_method: 0,
38 filter_method: 0,
39 interlace_method: 0,
40 metadata: "".to_string(),
41 path: path,
42 };
43
44 img.read_png_chunk(8, buff);
45 img
46 }
47
48 fn read_png_chunk(&mut self, start_byte: usize, buff: Vec<u8>) {
49 let data_buff = buff[start_byte..].to_vec();
50
51 let length = u32::from_le_bytes([data_buff[3], data_buff[2], data_buff[1], data_buff[0]]);
52 let chunk_type = str::from_utf8(&data_buff[4..8]).unwrap();
53
54 match chunk_type {
55 "IHDR" => {
56 self.width = u32::from_le_bytes([data_buff[11], data_buff[10], data_buff[9], data_buff[8]]);
57
58 self.height =
59 u32::from_le_bytes([data_buff[15], data_buff[14], data_buff[13], data_buff[12]]);
60
61 self.bit_depth = data_buff[16];
62 self.colour_type = data_buff[17];
63 self.compression_method = data_buff[18];
64 self.filter_method = data_buff[19];
65 self.interlace_method = data_buff[20];
66
67 self.read_png_chunk((length + 12) as usize, data_buff);
68 }
69 "iTXt" => {
70 let end_byte = (8 + length) as usize;
71 let d = str::from_utf8(&data_buff[8..end_byte]).unwrap();
72
73 self.metadata = d.to_string();
74
75 self.read_png_chunk((length + 12) as usize, data_buff);
76 }
77 "IEND" => {}
78 "IDAT" => {}
79 _ => {
80 self.read_png_chunk((length + 12) as usize, data_buff);
81 }
82 }
83 }
84}
85
86impl Serialize for PNGImage {
87 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
88 where
89 S: Serializer,
90 {
91 let mut s = serializer.serialize_struct("PNGImage", 7)?;
92 s.serialize_field("width", &self.width)?;
93 s.serialize_field("height", &self.height)?;
94 s.serialize_field("bit_depth", &self.bit_depth)?;
95 s.serialize_field("colour_type", &self.colour_type)?;
96 s.serialize_field("compression_method", &self.compression_method)?;
97 s.serialize_field("filter_method", &self.filter_method)?;
98 s.serialize_field("interlace_method", &self.interlace_method)?;
99 s.serialize_field("metadata", &self.metadata)?;
100 s.serialize_field("path", &self.path)?;
101 s.end()
102 }
103}