1use std::borrow::Cow;
2use std::io;
3use std::mem;
4use std::iter;
5use crate::common::Frame;
6use crate::MemoryLimit;
7
8use super::decoder::{DecodingError, OutputBuffer, PLTE_CHANNELS};
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> = &'a mut dyn FnMut(&mut OutputBuffer<'_>) -> Result<usize, DecodingError>;
27
28pub(crate) struct PixelConverter {
30 memory_limit: MemoryLimit,
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, memory_limit: MemoryLimit) -> Self {
38 Self {
39 memory_limit,
40 color_output,
41 buffer: Vec::new(),
42 global_palette: None,
43 }
44 }
45
46 pub(crate) fn check_buffer_size(&self, frame: &Frame<'_>) -> Result<usize, DecodingError> {
47 let pixel_bytes = self.memory_limit
48 .buffer_size(self.color_output, frame.width, frame.height)
49 .ok_or_else(|| io::Error::new(io::ErrorKind::OutOfMemory, "image is too large"))?;
50
51 debug_assert_eq!(
52 pixel_bytes, self.buffer_size(frame).unwrap(),
53 "Checked computation diverges from required buffer size"
54 );
55 Ok(pixel_bytes)
56 }
57
58 #[inline]
59 pub(crate) fn read_frame(&mut self, frame: &mut Frame<'_>, data_callback: FillBufferCallback<'_>) -> Result<(), DecodingError> {
60 let pixel_bytes = self.check_buffer_size(frame)?;
61 let mut vec = match mem::replace(&mut frame.buffer, Cow::Borrowed(&[])) {
62 Cow::Owned(mut vec) if vec.capacity() >= pixel_bytes => {
64 vec.resize(pixel_bytes, 0);
65 vec
66 },
67 _ => vec![0; pixel_bytes],
69 };
70 self.read_into_buffer(frame, &mut vec, data_callback)?;
71 frame.buffer = Cow::Owned(vec);
72 frame.interlaced = false;
73 Ok(())
74 }
75
76 #[inline]
77 pub(crate) const fn buffer_size(&self, frame: &Frame<'_>) -> Option<usize> {
78 self.line_length(frame).checked_mul(frame.height as usize)
79 }
80
81 #[inline]
82 pub(crate) const fn line_length(&self, frame: &Frame<'_>) -> usize {
83 use self::ColorOutput::{Indexed, RGBA};
84 match self.color_output {
85 RGBA => frame.width as usize * N_CHANNELS,
86 Indexed => frame.width as usize,
87 }
88 }
89
90 #[inline(never)]
92 pub(crate) fn fill_buffer(&mut self, current_frame: &Frame<'_>, mut buf: &mut [u8], data_callback: FillBufferCallback<'_>) -> Result<bool, DecodingError> {
93 loop {
94 let decode_into = match self.color_output {
95 ColorOutput::Indexed => &mut buf[..],
97 ColorOutput::RGBA => {
100 let buffer_size = buf.len() / N_CHANNELS;
101 if buffer_size == 0 {
102 return Err(DecodingError::format("odd-sized buffer"));
103 }
104 if self.buffer.len() < buffer_size {
105 self.buffer.resize(buffer_size, 0);
106 }
107 &mut self.buffer[..buffer_size]
108 }
109 };
110 match data_callback(&mut OutputBuffer::Slice(decode_into))? {
111 0 => return Ok(false),
112 bytes_decoded => {
113 match self.color_output {
114 ColorOutput::RGBA => {
115 let transparent = current_frame.transparent;
116 let palette: &[u8] = current_frame.palette.as_deref()
117 .or(self.global_palette.as_deref())
118 .unwrap_or_default(); let (pixels, rest) = buf.split_at_mut(bytes_decoded * N_CHANNELS);
121 buf = rest;
122
123 for (rgba, idx) in pixels.chunks_exact_mut(N_CHANNELS).zip(self.buffer.iter().copied().take(bytes_decoded)) {
124 let plte_offset = PLTE_CHANNELS * idx as usize;
125 if let Some(colors) = palette.get(plte_offset..plte_offset+PLTE_CHANNELS) {
126 rgba[0] = colors[0];
127 rgba[1] = colors[1];
128 rgba[2] = colors[2];
129 rgba[3] = if let Some(t) = transparent {
130 if t == idx { 0x00 } else { 0xFF }
131 } else {
132 0xFF
133 };
134 }
135 }
136 },
137 ColorOutput::Indexed => {
138 buf = &mut buf[bytes_decoded..];
139 }
140 }
141 if buf.is_empty() {
142 return Ok(true);
143 }
144 },
145 }
146 }
147 }
148
149 pub(crate) fn global_palette(&self) -> Option<&[u8]> {
150 self.global_palette.as_deref()
151 }
152
153 pub(crate) fn set_global_palette(&mut self, palette: Vec<u8>) {
154 self.global_palette = if !palette.is_empty() {
155 Some(palette)
156 } else {
157 None
158 };
159 }
160
161 pub(crate) fn read_into_buffer(&mut self, frame: &Frame<'_>, buf: &mut [u8], data_callback: FillBufferCallback<'_>) -> Result<(), DecodingError> {
165 if frame.interlaced {
166 let width = self.line_length(frame);
167 for row in (InterlaceIterator { len: frame.height, next: 0, pass: 0 }) {
168 let start = row * width;
170 let line = buf.get_mut(start..).and_then(|b| b.get_mut(..width))
172 .ok_or_else(|| DecodingError::format("buffer too small"))?;
173 if !self.fill_buffer(frame, line, data_callback)? {
174 return Err(DecodingError::format("image truncated"));
175 }
176 }
177 } else {
178 let buf = self.buffer_size(frame).and_then(|buffer_size| buf.get_mut(..buffer_size))
179 .ok_or_else(|| DecodingError::format("buffer too small"))?;
180 if !self.fill_buffer(frame, buf, data_callback)? {
181 return Err(DecodingError::format("image truncated"));
182 }
183 };
184 Ok(())
185 }
186}
187
188struct InterlaceIterator {
189 len: u16,
190 next: usize,
191 pass: usize,
192}
193
194impl iter::Iterator for InterlaceIterator {
195 type Item = usize;
196
197 #[inline]
198 fn next(&mut self) -> Option<Self::Item> {
199 if self.len == 0 {
200 return None;
201 }
202 let mut next = self.next + *[8, 8, 4, 2].get(self.pass)?;
205 while next >= self.len as usize {
206 debug_assert!(self.pass < 4);
207 next = *[4, 2, 1, 0].get(self.pass)?;
208 self.pass += 1;
209 }
210 mem::swap(&mut next, &mut self.next);
211 Some(next)
212 }
213}
214
215#[cfg(test)]
216mod test {
217 use super::InterlaceIterator;
218
219 #[test]
220 fn test_interlace_iterator() {
221 for &(len, expect) in &[
222 (0, &[][..]),
223 (1, &[0][..]),
224 (2, &[0, 1][..]),
225 (3, &[0, 2, 1][..]),
226 (4, &[0, 2, 1, 3][..]),
227 (5, &[0, 4, 2, 1, 3][..]),
228 (6, &[0, 4, 2, 1, 3, 5][..]),
229 (7, &[0, 4, 2, 6, 1, 3, 5][..]),
230 (8, &[0, 4, 2, 6, 1, 3, 5, 7][..]),
231 (9, &[0, 8, 4, 2, 6, 1, 3, 5, 7][..]),
232 (10, &[0, 8, 4, 2, 6, 1, 3, 5, 7, 9][..]),
233 (11, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9][..]),
234 (12, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]),
235 (13, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]),
236 (14, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11, 13][..]),
237 (15, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13][..]),
238 (16, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]),
239 (17, &[0, 8, 16, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]),
240 ] {
241 let iter = InterlaceIterator { len, next: 0, pass: 0 };
242 let lines = iter.collect::<Vec<_>>();
243 assert_eq!(lines, expect);
244 }
245 }
246
247 #[test]
248 fn interlace_max() {
249 let iter = InterlaceIterator { len: 0xFFFF, next: 0, pass: 0 };
250 assert_eq!(65533, iter.last().unwrap());
251 }
252}