1use glycin_common::shared_memory::SharedMemory;
2use glycin_common::{BinaryData, ExtendedMemoryFormat, MemoryFormat, MemoryFormatInfo};
3
4use super::Frame;
5use crate::editing::EditingFrame;
6use crate::{DimensionTooLargerError, FrameDetails, GenericContexts, ImageDetails, ProcessError};
7
8#[derive(Default, Clone, Debug)]
9pub struct Handler {
10 pub format_name: Option<String>,
11 pub default_bit_depth: Option<u8>,
12 pub supports_two_alpha_modes: bool,
13 pub supports_two_grayscale_modes: bool,
14}
15
16impl Handler {
17 pub fn format_name(mut self, format_name: impl ToString) -> Self {
18 self.format_name = Some(format_name.to_string());
19
20 self
21 }
22
23 pub fn default_bit_depth(mut self, default_bit_depth: u8) -> Self {
24 self.default_bit_depth = Some(default_bit_depth);
25
26 self
27 }
28
29 pub fn supports_two_alpha_modes(mut self, supports_two_alpha_modes: bool) -> Self {
30 self.supports_two_alpha_modes = supports_two_alpha_modes;
31
32 self
33 }
34
35 pub fn supports_two_grayscale_modes(mut self, supports_two_grayscale_modes: bool) -> Self {
36 self.supports_two_grayscale_modes = supports_two_grayscale_modes;
37
38 self
39 }
40
41 pub fn info(&self, decoder: &mut impl image::ImageDecoder) -> ImageDetails {
42 let (width, height) = decoder.dimensions();
43 let mut info = ImageDetails::new(width, height);
44 info.info_format_name.clone_from(&self.format_name);
45
46 info
47 }
48
49 pub fn frame(&self, mut decoder: impl image::ImageDecoder) -> Result<Frame, ProcessError> {
50 let simple_frame = self.editing_frame(&decoder)?;
51
52 let width = simple_frame.width;
53 let height = simple_frame.height;
54 let color_type = decoder.color_type();
55 let memory_format = memory_format_from_color_type(color_type);
56
57 let details = self.frame_details(&mut decoder);
58
59 let mut memory = SharedMemory::new(decoder.total_bytes()).expected_error()?;
60 decoder.read_image(&mut memory).expected_error()?;
61 let texture = memory.into_binary_data();
62
63 let mut frame = Frame::new(width, height, memory_format, texture)?;
64 frame.details = details.expected_error()?;
65
66 Ok(frame)
67 }
68
69 pub fn editing_frame(
70 &self,
71 decoder: &impl image::ImageDecoder,
72 ) -> Result<EditingFrame, ProcessError> {
73 let color_type = decoder.color_type();
74 let memory_format = ExtendedMemoryFormat::from(memory_format_from_color_type(color_type));
75 let (width, height) = decoder.dimensions();
76 let stride = memory_format
77 .n_bytes()
78 .u32()
79 .checked_mul(width)
80 .ok_or(DimensionTooLargerError)?;
81
82 Ok(EditingFrame {
83 width,
84 height,
85 stride,
86 memory_format,
87 })
88 }
89
90 pub fn frame_details(
91 &self,
92 decoder: &mut impl image::ImageDecoder,
93 ) -> Result<FrameDetails, ProcessError> {
94 let mut details = FrameDetails {
95 color_icc_profile: decoder
96 .icc_profile()
97 .ok()
98 .flatten()
99 .map(BinaryData::from_data)
100 .transpose()
101 .expected_error()?,
102 ..Default::default()
103 };
104
105 if let Some((alpha_channel, grayscale, bits)) =
106 channel_details(decoder.original_color_type())
107 {
108 if self.default_bit_depth != Some(bits) {
109 details.info_bit_depth = Some(bits);
110 }
111 if self.supports_two_alpha_modes {
112 details.info_alpha_channel = Some(alpha_channel);
113 }
114 if self.supports_two_grayscale_modes {
115 details.info_grayscale = Some(grayscale);
116 }
117 }
118
119 Ok(details)
120 }
121}
122
123pub fn memory_format_to_color_type(memory_format: &MemoryFormat) -> Option<image::ColorType> {
137 match memory_format {
138 MemoryFormat::G8 => Some(image::ColorType::L8),
139 MemoryFormat::G8a8 => Some(image::ColorType::La8),
140 MemoryFormat::R8g8b8 => Some(image::ColorType::Rgb8),
141 MemoryFormat::R8g8b8a8 => Some(image::ColorType::Rgba8),
142 MemoryFormat::G16 => Some(image::ColorType::L16),
143 MemoryFormat::G16a16 => Some(image::ColorType::La16),
144 MemoryFormat::R16g16b16 => Some(image::ColorType::Rgb16),
145 MemoryFormat::R16g16b16a16 => Some(image::ColorType::Rgba16),
146 MemoryFormat::R32g32b32Float => Some(image::ColorType::Rgb32F),
147 MemoryFormat::R32g32b32a32Float => Some(image::ColorType::Rgba32F),
148 _ => None,
149 }
150}
151
152pub fn extended_memory_format_to_color_type(
153 extended_memory_format: &ExtendedMemoryFormat,
154) -> Option<image::ColorType> {
155 match extended_memory_format {
156 ExtendedMemoryFormat::Basic(basic) => memory_format_to_color_type(basic),
157 _ => None,
158 }
159}
160
161pub fn memory_format_from_color_type(color_type: image::ColorType) -> MemoryFormat {
162 match color_type {
163 image::ColorType::L8 => MemoryFormat::G8,
164 image::ColorType::La8 => MemoryFormat::G8a8,
165 image::ColorType::Rgb8 => MemoryFormat::R8g8b8,
166 image::ColorType::Rgba8 => MemoryFormat::R8g8b8a8,
167 image::ColorType::L16 => MemoryFormat::G16,
168 image::ColorType::La16 => MemoryFormat::G16a16,
169 image::ColorType::Rgb16 => MemoryFormat::R16g16b16,
170 image::ColorType::Rgba16 => MemoryFormat::R16g16b16a16,
171 image::ColorType::Rgb32F => MemoryFormat::R32g32b32Float,
172 image::ColorType::Rgba32F => MemoryFormat::R32g32b32a32Float,
173 _ => unimplemented!(),
174 }
175}
176
177pub fn channel_details(color_type: image::ExtendedColorType) -> Option<(bool, bool, u8)> {
178 Some(match color_type {
179 image::ExtendedColorType::A8 => (true, false, 8),
180 image::ExtendedColorType::L1 => (false, true, 1),
181 image::ExtendedColorType::La1 => (true, true, 1),
182 image::ExtendedColorType::Rgb1 => (false, false, 1),
183 image::ExtendedColorType::Rgba1 => (true, false, 1),
184 image::ExtendedColorType::L2 => (false, true, 2),
185 image::ExtendedColorType::La2 => (true, true, 2),
186 image::ExtendedColorType::Rgb2 => (false, false, 2),
187 image::ExtendedColorType::Rgba2 => (true, false, 2),
188 image::ExtendedColorType::L4 => (false, true, 4),
189 image::ExtendedColorType::La4 => (true, true, 4),
190 image::ExtendedColorType::Rgb4 => (false, false, 4),
191 image::ExtendedColorType::Rgba4 => (true, false, 4),
192 image::ExtendedColorType::L8 => (false, true, 8),
193 image::ExtendedColorType::La8 => (true, true, 8),
194 image::ExtendedColorType::Rgb8 => (false, false, 8),
195 image::ExtendedColorType::Rgba8 => (true, false, 8),
196 image::ExtendedColorType::L16 => (false, true, 16),
197 image::ExtendedColorType::La16 => (true, true, 16),
198 image::ExtendedColorType::Rgb16 => (false, false, 16),
199 image::ExtendedColorType::Rgba16 => (true, false, 16),
200 image::ExtendedColorType::Bgr8 => (false, false, 8),
201 image::ExtendedColorType::Bgra8 => (true, false, 8),
202 image::ExtendedColorType::Rgb32F => (false, false, 32),
203 image::ExtendedColorType::Rgba32F => (true, false, 32),
204 image::ExtendedColorType::Unknown(bits) => (false, false, bits),
205 _ => return None,
206 })
207}