Skip to main content

glycin_utils/
image_rs.rs

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    /*
97    pub fn editing_frame(
98        &self,
99        decoder: &impl image::ImageDecoder,
100    ) -> Result<EditingFrame, ProcessError> {
101        let color_type = decoder.color_type();
102        let memory_format = ExtendedMemoryFormat::from(memory_format_from_color_type(color_type));
103        let (width, height) = decoder.dimensions();
104        let stride = memory_format
105            .n_bytes()
106            .u32()
107            .checked_mul(width)
108            .ok_or(DimensionTooLargerError)?;
109
110        Ok(EditingFrame {
111            width,
112            height,
113            stride,
114            memory_format,
115        })
116    }*/
117
118    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
151/*
152impl ImageInfo {
153    pub fn from_decoder(
154        decoder: &mut impl image::ImageDecoder,
155        _format_name: impl ToString,
156    ) -> Self {
157        let (width, height) = decoder.dimensions();
158
159        Self::new(width, height)
160    }
161}
162     */
163
164pub 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}