msg_tool\scripts\kirikiri\image/
tlg.rs1use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::img::*;
6use anyhow::Result;
7use libtlg_rs::*;
8use std::io::{Read, Seek};
9
10#[derive(Debug)]
11pub struct TlgImageBuilder {}
13
14impl TlgImageBuilder {
15 pub const fn new() -> Self {
17 TlgImageBuilder {}
18 }
19}
20
21impl ScriptBuilder for TlgImageBuilder {
22 fn default_encoding(&self) -> Encoding {
23 Encoding::Cp932
24 }
25
26 fn build_script(
27 &self,
28 data: Vec<u8>,
29 _filename: &str,
30 _encoding: Encoding,
31 _archive_encoding: Encoding,
32 config: &ExtraConfig,
33 _archive: Option<&Box<dyn Script>>,
34 ) -> Result<Box<dyn Script>> {
35 Ok(Box::new(TlgImage::new(MemReader::new(data), config)?))
36 }
37
38 fn extensions(&self) -> &'static [&'static str] {
39 &["tlg", "tlg5", "tlg6"]
40 }
41
42 fn script_type(&self) -> &'static ScriptType {
43 &ScriptType::KirikiriTlg
44 }
45
46 fn is_image(&self) -> bool {
47 true
48 }
49
50 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
51 if buf_len >= 11 {
52 if is_valid_tlg(buf) {
53 return Some(255);
54 }
55 }
56 None
57 }
58
59 fn can_create_image_file(&self) -> bool {
60 true
61 }
62
63 fn create_image_file<'a>(
64 &'a self,
65 mut data: ImageData,
66 _filename: &str,
67 writer: Box<dyn WriteSeek + 'a>,
68 _options: &ExtraConfig,
69 ) -> Result<()> {
70 if data.depth != 8 {
71 return Err(anyhow::anyhow!("Unsupported image depth: {}", data.depth));
72 }
73 let color_type = match data.color_type {
74 ImageColorType::Bgr => TlgColorType::Bgr24,
75 ImageColorType::Bgra => TlgColorType::Bgra32,
76 ImageColorType::Grayscale => TlgColorType::Grayscale8,
77 ImageColorType::Rgb => {
78 convert_rgb_to_bgr(&mut data)?;
79 TlgColorType::Bgr24
80 }
81 ImageColorType::Rgba => {
82 convert_rgba_to_bgra(&mut data)?;
83 TlgColorType::Bgra32
84 }
85 };
86 let tlg = Tlg {
87 width: data.width,
88 height: data.height,
89 color: color_type,
90 data: data.data,
91 tags: Default::default(),
92 version: 5, };
94 save_tlg(&tlg, writer)?;
95 Ok(())
96 }
97}
98
99#[derive(Debug)]
100pub struct TlgImage {
102 data: Tlg,
103}
104
105impl TlgImage {
106 pub fn new<T: Read + Seek>(data: T, _config: &ExtraConfig) -> Result<Self> {
111 let tlg = load_tlg(data)?;
112 Ok(TlgImage { data: tlg })
113 }
114}
115
116impl Script for TlgImage {
117 fn default_output_script_type(&self) -> OutputScriptType {
118 OutputScriptType::Json
119 }
120
121 fn default_format_type(&self) -> FormatOptions {
122 FormatOptions::None
123 }
124
125 fn is_image(&self) -> bool {
126 true
127 }
128
129 fn export_image(&self) -> Result<ImageData> {
130 Ok(ImageData {
131 width: self.data.width,
132 height: self.data.height,
133 color_type: match self.data.color {
134 TlgColorType::Bgr24 => ImageColorType::Bgr,
135 TlgColorType::Bgra32 => ImageColorType::Bgra,
136 TlgColorType::Grayscale8 => ImageColorType::Grayscale,
137 },
138 depth: 8,
139 data: self.data.data.clone(),
140 })
141 }
142
143 fn import_image<'a>(
144 &'a self,
145 mut data: ImageData,
146 _filename: &str,
147 file: Box<dyn WriteSeek + 'a>,
148 ) -> Result<()> {
149 if data.depth != 8 {
150 return Err(anyhow::anyhow!("Unsupported image depth: {}", data.depth));
151 }
152 let color_type = match data.color_type {
153 ImageColorType::Bgr => TlgColorType::Bgr24,
154 ImageColorType::Bgra => TlgColorType::Bgra32,
155 ImageColorType::Grayscale => TlgColorType::Grayscale8,
156 ImageColorType::Rgb => {
157 convert_rgb_to_bgr(&mut data)?;
158 TlgColorType::Bgr24
159 }
160 ImageColorType::Rgba => {
161 convert_rgba_to_bgra(&mut data)?;
162 TlgColorType::Bgra32
163 }
164 };
165 let tlg = Tlg {
166 width: data.width,
167 height: data.height,
168 color: color_type,
169 data: data.data,
170 tags: self.data.tags.clone(),
171 version: 5, };
173 save_tlg(&tlg, file)?;
174 Ok(())
175 }
176}