msg_tool\scripts\softpal\img\pgd/
ge.rs

1use super::base::*;
2use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::struct_pack::*;
6use anyhow::Result;
7use std::io::{Read, Seek};
8
9#[derive(Debug)]
10pub struct PgdGeBuilder {}
11
12impl PgdGeBuilder {
13    pub fn new() -> Self {
14        Self {}
15    }
16}
17
18impl ScriptBuilder for PgdGeBuilder {
19    fn default_encoding(&self) -> Encoding {
20        Encoding::Cp932
21    }
22
23    fn build_script(
24        &self,
25        buf: Vec<u8>,
26        _filename: &str,
27        _encoding: Encoding,
28        _archive_encoding: Encoding,
29        config: &ExtraConfig,
30        _archive: Option<&Box<dyn Script>>,
31    ) -> Result<Box<dyn Script>> {
32        Ok(Box::new(PgdGe::new(MemReader::new(buf), config)?))
33    }
34
35    fn extensions(&self) -> &'static [&'static str] {
36        &["pgd"]
37    }
38
39    fn script_type(&self) -> &'static ScriptType {
40        &ScriptType::SoftpalPgdGe
41    }
42
43    fn is_image(&self) -> bool {
44        true
45    }
46
47    fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
48        if buf_len >= 4 && buf.starts_with(b"GE \0") {
49            return Some(20);
50        }
51        None
52    }
53
54    fn can_create_image_file(&self) -> bool {
55        true
56    }
57
58    fn create_image_file<'a>(
59        &'a self,
60        data: ImageData,
61        _filename: &str,
62        mut writer: Box<dyn WriteSeek + 'a>,
63        options: &ExtraConfig,
64    ) -> Result<()> {
65        let header = PgdGeHeader {
66            offset_x: 0,
67            offset_y: 0,
68            width: data.width,
69            height: data.height,
70            canvas_width: data.width,
71            canvas_height: data.height,
72            mode: 3,
73            _unk: 0,
74        };
75        writer.write_all(b"GE \0")?;
76        header.pack(&mut writer, false, Encoding::Utf8, &None)?;
77        PgdWriter::new(data, options.pgd_fake_compress)
78            .with_method(3)
79            .pack_ge(&mut writer)?;
80        Ok(())
81    }
82}
83
84#[derive(Debug)]
85pub struct PgdGe {
86    header: PgdGeHeader,
87    data: ImageData,
88    fake_compress: bool,
89}
90
91impl PgdGe {
92    pub fn new<T: Read + Seek>(mut input: T, config: &ExtraConfig) -> Result<Self> {
93        let mut magic = [0u8; 4];
94        input.read_exact(&mut magic)?;
95        if &magic != b"GE \0" {
96            return Err(anyhow::anyhow!("Not a valid PGD GE image"));
97        }
98        let header = PgdGeHeader::unpack(&mut input, false, Encoding::Utf8, &None)?;
99        let reader = PgdReader::with_ge_header(input, &header)?;
100        let data = reader.unpack_ge()?;
101        Ok(Self {
102            header,
103            data,
104            fake_compress: config.pgd_fake_compress,
105        })
106    }
107}
108
109impl Script for PgdGe {
110    fn default_output_script_type(&self) -> OutputScriptType {
111        OutputScriptType::Json
112    }
113
114    fn default_format_type(&self) -> FormatOptions {
115        FormatOptions::None
116    }
117
118    fn is_image(&self) -> bool {
119        true
120    }
121
122    fn export_image(&self) -> Result<ImageData> {
123        Ok(self.data.clone())
124    }
125
126    fn import_image<'a>(
127        &'a self,
128        data: ImageData,
129        _filename: &str,
130        mut file: Box<dyn WriteSeek + 'a>,
131    ) -> Result<()> {
132        let mut header = self.header.clone();
133        if data.height != self.data.height {
134            return Err(anyhow::anyhow!(
135                "Image height does not match: expected {}, got {}",
136                self.data.height,
137                data.height
138            ));
139        }
140        if data.width != self.data.width {
141            return Err(anyhow::anyhow!(
142                "Image width does not match: expected {}, got {}",
143                self.data.width,
144                data.width
145            ));
146        }
147        header.mode = 3;
148        file.write_all(b"GE \0")?;
149        header.pack(&mut file, false, Encoding::Utf8, &None)?;
150        PgdWriter::new(data, self.fake_compress)
151            .with_method(3)
152            .pack_ge(&mut file)?;
153        Ok(())
154    }
155}