1use alloc::borrow::Cow;
2use alloc::vec::Vec;
3use core::iter;
4use core::mem;
5
6use super::decoder::{DecodingError, OutputBuffer, PLTE_CHANNELS};
7use crate::common::Frame;
8use crate::MemoryLimit;
9
10pub(crate) const N_CHANNELS: usize = 4;
11
12#[derive(Clone, Copy, Debug, PartialEq)]
14#[repr(u8)]
15pub enum ColorOutput {
16 RGBA = 0,
22 Indexed = 1,
24}
25
26pub(crate) type FillBufferCallback<'a> =
27 &'a mut dyn FnMut(&mut OutputBuffer<'_>) -> Result<usize, DecodingError>;
28
29pub(crate) struct PixelConverter {
31 color_output: ColorOutput,
32 buffer: Vec<u8>,
33 global_palette: Option<Vec<u8>>,
34}
35
36impl PixelConverter {
37 pub(crate) const fn new(color_output: ColorOutput) -> Self {
38 Self {
39 color_output,
40 buffer: Vec::new(),
41 global_palette: None,
42 }
43 }
44
45 pub(crate) fn check_buffer_size(
46 &self,
47 frame: &Frame<'_>,
48 memory_limit: &MemoryLimit,
49 ) -> Result<usize, DecodingError> {
50 let pixel_bytes = memory_limit
51 .buffer_size(self.color_output, frame.width, frame.height)
52 .ok_or_else(|| DecodingError::OutOfMemory)?;
53
54 debug_assert_eq!(
55 pixel_bytes,
56 self.buffer_size(frame).unwrap(),
57 "Checked computation diverges from required buffer size"
58 );
59 Ok(pixel_bytes)
60 }
61
62 #[inline]
63 pub(crate) fn read_frame(
64 &mut self,
65 frame: &mut Frame<'_>,
66 data_callback: FillBufferCallback<'_>,
67 memory_limit: &MemoryLimit,
68 ) -> Result<(), DecodingError> {
69 let pixel_bytes = self.check_buffer_size(frame, memory_limit)?;
70 let mut vec = match mem::replace(&mut frame.buffer, Cow::Borrowed(&[])) {
71 Cow::Owned(mut vec) if vec.capacity() >= pixel_bytes => {
73 vec.resize(pixel_bytes, 0);
74 vec
75 }
76 _ => vec![0; pixel_bytes],
78 };
79 self.read_into_buffer(frame, &mut vec, data_callback)?;
80 frame.buffer = Cow::Owned(vec);
81 frame.interlaced = false;
82 Ok(())
83 }
84
85 #[inline]
86 pub(crate) const fn buffer_size(&self, frame: &Frame<'_>) -> Option<usize> {
87 self.line_length(frame).checked_mul(frame.height as usize)
88 }
89
90 #[inline]
91 pub(crate) const fn line_length(&self, frame: &Frame<'_>) -> usize {
92 use self::ColorOutput::{Indexed, RGBA};
93 match self.color_output {
94 RGBA => frame.width as usize * N_CHANNELS,
95 Indexed => frame.width as usize,
96 }
97 }
98
99 #[inline(never)]
101 pub(crate) fn fill_buffer(
102 &mut self,
103 current_frame: &Frame<'_>,
104 mut buf: &mut [u8],
105 data_callback: FillBufferCallback<'_>,
106 ) -> Result<bool, DecodingError> {
107 loop {
108 let decode_into = match self.color_output {
109 ColorOutput::Indexed => &mut buf[..],
111 ColorOutput::RGBA => {
114 let buffer_size = buf.len() / N_CHANNELS;
115 if buffer_size == 0 {
116 return Err(DecodingError::format("odd-sized buffer"));
117 }
118 if self.buffer.len() < buffer_size {
119 self.buffer.resize(buffer_size, 0);
120 }
121 &mut self.buffer[..buffer_size]
122 }
123 };
124 match data_callback(&mut OutputBuffer::Slice(decode_into))? {
125 0 => return Ok(false),
126 bytes_decoded => {
127 match self.color_output {
128 ColorOutput::RGBA => {
129 let transparent = current_frame.transparent;
130 let palette: &[u8] = current_frame
131 .palette
132 .as_deref()
133 .or(self.global_palette.as_deref())
134 .unwrap_or_default(); let (pixels, rest) = buf.split_at_mut(bytes_decoded * N_CHANNELS);
137 buf = rest;
138
139 for (rgba, idx) in pixels
140 .chunks_exact_mut(N_CHANNELS)
141 .zip(self.buffer.iter().copied().take(bytes_decoded))
142 {
143 let plte_offset = PLTE_CHANNELS * idx as usize;
144 if let Some(colors) =
145 palette.get(plte_offset..plte_offset + PLTE_CHANNELS)
146 {
147 rgba[0] = colors[0];
148 rgba[1] = colors[1];
149 rgba[2] = colors[2];
150 rgba[3] = if let Some(t) = transparent {
151 if t == idx {
152 0x00
153 } else {
154 0xFF
155 }
156 } else {
157 0xFF
158 };
159 }
160 }
161 }
162 ColorOutput::Indexed => {
163 buf = &mut buf[bytes_decoded..];
164 }
165 }
166 if buf.is_empty() {
167 return Ok(true);
168 }
169 }
170 }
171 }
172 }
173
174 pub(crate) fn global_palette(&self) -> Option<&[u8]> {
175 self.global_palette.as_deref()
176 }
177
178 pub(crate) fn set_global_palette(&mut self, palette: Vec<u8>) {
179 self.global_palette = if !palette.is_empty() {
180 Some(palette)
181 } else {
182 None
183 };
184 }
185
186 pub(crate) fn read_into_buffer(
190 &mut self,
191 frame: &Frame<'_>,
192 buf: &mut [u8],
193 data_callback: FillBufferCallback<'_>,
194 ) -> Result<(), DecodingError> {
195 if frame.interlaced {
196 let width = self.line_length(frame);
197 for row in (InterlaceIterator {
198 len: frame.height,
199 next: 0,
200 pass: 0,
201 }) {
202 let start = row * width;
204 let line = buf
206 .get_mut(start..)
207 .and_then(|b| b.get_mut(..width))
208 .ok_or_else(|| DecodingError::format("buffer too small"))?;
209 if !self.fill_buffer(frame, line, data_callback)? {
210 return Err(DecodingError::format("image truncated"));
211 }
212 }
213 } else {
214 let buf = self
215 .buffer_size(frame)
216 .and_then(|buffer_size| buf.get_mut(..buffer_size))
217 .ok_or_else(|| DecodingError::format("buffer too small"))?;
218 if !self.fill_buffer(frame, buf, data_callback)? {
219 return Err(DecodingError::format("image truncated"));
220 }
221 };
222 Ok(())
223 }
224}
225
226struct InterlaceIterator {
227 len: u16,
228 next: usize,
229 pass: usize,
230}
231
232impl iter::Iterator for InterlaceIterator {
233 type Item = usize;
234
235 #[inline]
236 fn next(&mut self) -> Option<Self::Item> {
237 if self.len == 0 {
238 return None;
239 }
240 let mut next = self.next + *[8, 8, 4, 2].get(self.pass)?;
243 while next >= self.len as usize {
244 debug_assert!(self.pass < 4);
245 next = *[4, 2, 1, 0].get(self.pass)?;
246 self.pass += 1;
247 }
248 mem::swap(&mut next, &mut self.next);
249 Some(next)
250 }
251}
252
253#[cfg(test)]
254mod test {
255 use alloc::vec::Vec;
256
257 use super::InterlaceIterator;
258
259 #[rustfmt::skip]
260 #[test]
261 fn test_interlace_iterator() {
262 for &(len, expect) in &[
263 (0, &[][..]),
264 (1, &[0][..]),
265 (2, &[0, 1][..]),
266 (3, &[0, 2, 1][..]),
267 (4, &[0, 2, 1, 3][..]),
268 (5, &[0, 4, 2, 1, 3][..]),
269 (6, &[0, 4, 2, 1, 3, 5][..]),
270 (7, &[0, 4, 2, 6, 1, 3, 5][..]),
271 (8, &[0, 4, 2, 6, 1, 3, 5, 7][..]),
272 (9, &[0, 8, 4, 2, 6, 1, 3, 5, 7][..]),
273 (10, &[0, 8, 4, 2, 6, 1, 3, 5, 7, 9][..]),
274 (11, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9][..]),
275 (12, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]),
276 (13, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]),
277 (14, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11, 13][..]),
278 (15, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13][..]),
279 (16, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]),
280 (17, &[0, 8, 16, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]),
281 ] {
282 let iter = InterlaceIterator { len, next: 0, pass: 0 };
283 let lines = iter.collect::<Vec<_>>();
284 assert_eq!(lines, expect);
285 }
286 }
287
288 #[test]
289 fn interlace_max() {
290 let iter = InterlaceIterator {
291 len: 0xFFFF,
292 next: 0,
293 pass: 0,
294 };
295 assert_eq!(65533, iter.last().unwrap());
296 }
297}