msg_tool\scripts\hexen_haus\img/
png.rs1use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::img::*;
6use anyhow::Result;
7use std::io::{Read, Seek, SeekFrom};
8
9#[derive(Debug)]
10pub struct PngImageBuilder {}
12
13impl PngImageBuilder {
14 pub fn new() -> Self {
16 PngImageBuilder {}
17 }
18}
19
20impl ScriptBuilder for PngImageBuilder {
21 fn default_encoding(&self) -> Encoding {
22 Encoding::Cp932
23 }
24
25 fn build_script(
26 &self,
27 data: Vec<u8>,
28 _filename: &str,
29 _encoding: Encoding,
30 _archive_encoding: Encoding,
31 config: &ExtraConfig,
32 _archive: Option<&Box<dyn Script>>,
33 ) -> Result<Box<dyn Script + Send + Sync>> {
34 Ok(Box::new(PngImage::new(MemReader::new(data), config)?))
35 }
36
37 fn extensions(&self) -> &'static [&'static str] {
38 &["png"]
39 }
40
41 fn script_type(&self) -> &'static ScriptType {
42 &ScriptType::HexenHausPng
43 }
44
45 fn is_image(&self) -> bool {
46 true
47 }
48
49 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
50 if buf_len >= 4 && buf.starts_with(b"IMGD") {
51 return Some(10);
52 }
53 None
54 }
55}
56
57#[derive(Clone, Debug)]
58pub struct ExtraInfo {
60 pub offset_x: u32,
62 pub offset_y: u32,
64}
65
66impl AnyDebug for ExtraInfo {
67 fn as_any(&self) -> &dyn std::any::Any {
68 self
69 }
70}
71
72#[derive(Debug)]
73pub struct PngImage {
74 reader: MemReader,
75 extra: Option<ExtraInfo>,
76}
77
78impl PngImage {
79 pub fn new(mut reader: MemReader, _config: &ExtraConfig) -> Result<Self> {
81 let mut header = [0; 4];
82 reader.read_exact(&mut header)?;
83 if &header != b"IMGD" {
84 return Err(anyhow::anyhow!("Not a valid HexenHaus PNG image"));
85 }
86 reader.seek(SeekFrom::End(-14))?;
87 let cnt = reader.read_exact_vec(12)?;
88 let extra = if cnt.starts_with(b"CNTR") {
89 let mut cnt_reader = MemReaderRef::new(&cnt[4..]);
90 let offset_x = cnt_reader.read_u32()?;
91 let offset_y = cnt_reader.read_u32()?;
92 Some(ExtraInfo { offset_x, offset_y })
93 } else {
94 None
95 };
96 Ok(PngImage { reader, extra })
97 }
98}
99
100impl Script for PngImage {
101 fn default_output_script_type(&self) -> OutputScriptType {
102 OutputScriptType::Json
103 }
104
105 fn default_format_type(&self) -> FormatOptions {
106 FormatOptions::None
107 }
108
109 fn is_image(&self) -> bool {
110 true
111 }
112
113 fn export_image(&self) -> Result<ImageData> {
114 let mut reader = self.reader.to_ref();
115 reader.pos = 0;
116 let reader = StreamRegion::with_start_pos(reader, 0x10)?;
117 let img = load_png(reader)?;
118 Ok(img)
119 }
120
121 fn extra_info<'a>(&'a self) -> Option<Box<dyn AnyDebug + 'a>> {
122 self.extra
123 .as_ref()
124 .map(|e| Box::new(e.clone()) as Box<dyn AnyDebug>)
125 }
126}