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}