1use glycin_common::{ExtendedMemoryFormat, MemoryFormat, MemoryFormatInfo};
2
3use crate::editing::EditingFrame;
4use crate::{
5 ByteData, DimensionTooLargerError, Frame, FrameDetails, GenericContexts, ImageDetails,
6 ProcessError,
7};
8
9#[derive(Default, Clone, Debug)]
10pub struct Handler {
11 pub format_name: Option<String>,
12 pub default_bit_depth: Option<u8>,
13 pub supports_two_alpha_modes: bool,
14 pub supports_two_grayscale_modes: bool,
15}
16
17impl Handler {
18 pub fn format_name(mut self, format_name: impl ToString) -> Self {
19 self.format_name = Some(format_name.to_string());
20
21 self
22 }
23
24 pub fn default_bit_depth(mut self, default_bit_depth: u8) -> Self {
25 self.default_bit_depth = Some(default_bit_depth);
26
27 self
28 }
29
30 pub fn supports_two_alpha_modes(mut self, supports_two_alpha_modes: bool) -> Self {
31 self.supports_two_alpha_modes = supports_two_alpha_modes;
32
33 self
34 }
35
36 pub fn supports_two_grayscale_modes(mut self, supports_two_grayscale_modes: bool) -> Self {
37 self.supports_two_grayscale_modes = supports_two_grayscale_modes;
38
39 self
40 }
41
42 pub fn info<B: ByteData>(&self, decoder: &mut impl image::ImageDecoder) -> ImageDetails<B> {
43 let (width, height) = decoder.dimensions();
44 let mut info = ImageDetails::new(width, height);
45 info.info_format_name.clone_from(&self.format_name);
46
47 info
48 }
49
50 pub fn frame<B: ByteData>(
51 &self,
52 mut decoder: impl image::ImageDecoder,
53 ) -> Result<Frame<B>, ProcessError> {
54 let color_type = decoder.color_type();
55 let details = self.frame_details(&mut decoder);
56
57 let editing_frame = self.editing_frame(decoder)?;
58
59 let width = editing_frame.width;
60 let height = editing_frame.height;
61 let memory_format = memory_format_from_color_type(color_type);
62
63 let texture = editing_frame.texture;
64
65 let mut frame = Frame::new(width, height, memory_format, texture)?;
66 frame.details = details.expected_error()?;
67
68 Ok(frame)
69 }
70
71 pub fn editing_frame<B: ByteData>(
72 &self,
73 decoder: impl image::ImageDecoder,
74 ) -> Result<EditingFrame<B>, ProcessError> {
75 let color_type = decoder.color_type();
76 let memory_format = ExtendedMemoryFormat::from(memory_format_from_color_type(color_type));
77 let (width, height) = decoder.dimensions();
78 let stride = memory_format
79 .n_bytes()
80 .u32()
81 .checked_mul(width)
82 .ok_or(DimensionTooLargerError)?;
83
84 let mut texture = B::new(decoder.total_bytes()).expected_error()?;
85 decoder.read_image(&mut texture).expected_error()?;
86
87 Ok(EditingFrame {
88 width,
89 height,
90 stride,
91 memory_format,
92 texture,
93 })
94 }
95
96 pub fn frame_details<B: ByteData>(
119 &self,
120 decoder: &mut impl image::ImageDecoder,
121 ) -> Result<FrameDetails<B>, ProcessError> {
122 let mut details = FrameDetails {
123 color_icc_profile: decoder
124 .icc_profile()
125 .ok()
126 .flatten()
127 .map(B::try_from_vec)
128 .transpose()
129 .expected_error()?,
130 ..Default::default()
131 };
132
133 if let Some((alpha_channel, grayscale, bits)) =
134 channel_details(decoder.original_color_type())
135 {
136 if self.default_bit_depth != Some(bits) {
137 details.info_bit_depth = Some(bits);
138 }
139 if self.supports_two_alpha_modes {
140 details.info_alpha_channel = Some(alpha_channel);
141 }
142 if self.supports_two_grayscale_modes {
143 details.info_grayscale = Some(grayscale);
144 }
145 }
146
147 Ok(details)
148 }
149}
150
151pub fn memory_format_to_color_type(memory_format: &MemoryFormat) -> Option<image::ColorType> {
165 match memory_format {
166 MemoryFormat::G8 => Some(image::ColorType::L8),
167 MemoryFormat::G8a8 => Some(image::ColorType::La8),
168 MemoryFormat::R8g8b8 => Some(image::ColorType::Rgb8),
169 MemoryFormat::R8g8b8a8 => Some(image::ColorType::Rgba8),
170 MemoryFormat::G16 => Some(image::ColorType::L16),
171 MemoryFormat::G16a16 => Some(image::ColorType::La16),
172 MemoryFormat::R16g16b16 => Some(image::ColorType::Rgb16),
173 MemoryFormat::R16g16b16a16 => Some(image::ColorType::Rgba16),
174 MemoryFormat::R32g32b32Float => Some(image::ColorType::Rgb32F),
175 MemoryFormat::R32g32b32a32Float => Some(image::ColorType::Rgba32F),
176 _ => None,
177 }
178}
179
180pub fn extended_memory_format_to_color_type(
181 extended_memory_format: &ExtendedMemoryFormat,
182) -> Option<image::ColorType> {
183 match extended_memory_format {
184 ExtendedMemoryFormat::Basic(basic) => memory_format_to_color_type(basic),
185 _ => None,
186 }
187}
188
189pub fn memory_format_from_color_type(color_type: image::ColorType) -> MemoryFormat {
190 match color_type {
191 image::ColorType::L8 => MemoryFormat::G8,
192 image::ColorType::La8 => MemoryFormat::G8a8,
193 image::ColorType::Rgb8 => MemoryFormat::R8g8b8,
194 image::ColorType::Rgba8 => MemoryFormat::R8g8b8a8,
195 image::ColorType::L16 => MemoryFormat::G16,
196 image::ColorType::La16 => MemoryFormat::G16a16,
197 image::ColorType::Rgb16 => MemoryFormat::R16g16b16,
198 image::ColorType::Rgba16 => MemoryFormat::R16g16b16a16,
199 image::ColorType::Rgb32F => MemoryFormat::R32g32b32Float,
200 image::ColorType::Rgba32F => MemoryFormat::R32g32b32a32Float,
201 _ => unimplemented!(),
202 }
203}
204
205pub fn channel_details(color_type: image::ExtendedColorType) -> Option<(bool, bool, u8)> {
206 Some(match color_type {
207 image::ExtendedColorType::A8 => (true, false, 8),
208 image::ExtendedColorType::L1 => (false, true, 1),
209 image::ExtendedColorType::La1 => (true, true, 1),
210 image::ExtendedColorType::Rgb1 => (false, false, 1),
211 image::ExtendedColorType::Rgba1 => (true, false, 1),
212 image::ExtendedColorType::L2 => (false, true, 2),
213 image::ExtendedColorType::La2 => (true, true, 2),
214 image::ExtendedColorType::Rgb2 => (false, false, 2),
215 image::ExtendedColorType::Rgba2 => (true, false, 2),
216 image::ExtendedColorType::L4 => (false, true, 4),
217 image::ExtendedColorType::La4 => (true, true, 4),
218 image::ExtendedColorType::Rgb4 => (false, false, 4),
219 image::ExtendedColorType::Rgba4 => (true, false, 4),
220 image::ExtendedColorType::L8 => (false, true, 8),
221 image::ExtendedColorType::La8 => (true, true, 8),
222 image::ExtendedColorType::Rgb8 => (false, false, 8),
223 image::ExtendedColorType::Rgba8 => (true, false, 8),
224 image::ExtendedColorType::L16 => (false, true, 16),
225 image::ExtendedColorType::La16 => (true, true, 16),
226 image::ExtendedColorType::Rgb16 => (false, false, 16),
227 image::ExtendedColorType::Rgba16 => (true, false, 16),
228 image::ExtendedColorType::Bgr8 => (false, false, 8),
229 image::ExtendedColorType::Bgra8 => (true, false, 8),
230 image::ExtendedColorType::Rgb32F => (false, false, 32),
231 image::ExtendedColorType::Rgba32F => (true, false, 32),
232 image::ExtendedColorType::Unknown(bits) => (false, false, bits),
233 _ => return None,
234 })
235}