1use std::borrow::Cow;
2use std::io;
3use std::iter::FusedIterator;
4use std::mem;
5
6use std::io::prelude::*;
7use std::num::NonZeroU64;
8use std::convert::{TryFrom, TryInto};
9
10use crate::Repeat;
11use crate::common::{Block, Frame};
12
13mod decoder;
14mod converter;
15
16pub use self::decoder::{
17 PLTE_CHANNELS, StreamingDecoder, Decoded, DecodingError, DecodingFormatError,
18 Version, FrameDataType, OutputBuffer, FrameDecoder
19};
20
21use self::converter::PixelConverter;
22pub use self::converter::ColorOutput;
23
24#[derive(Clone, Debug)]
25pub enum MemoryLimit {
27 Unlimited,
37 Bytes(NonZeroU64),
47}
48
49impl MemoryLimit {
50 fn check_size(&self, size: usize) -> Result<(), DecodingError> {
51 match self {
52 Self::Unlimited => Ok(()),
53 Self::Bytes(limit) => {
54 if size as u64 <= limit.get() {
55 Ok(())
56 } else {
57 Err(DecodingError::format("memory limit reached"))
58 }
59 },
60 }
61 }
62
63 fn buffer_size(&self, color: ColorOutput, width: u16, height: u16) -> Option<usize> {
64 let pixels = u64::from(width) * u64::from(height);
65
66 let bytes_per_pixel = match color {
67 ColorOutput::Indexed => 1,
68 ColorOutput::RGBA => 4,
69 };
70
71 let total_bytes = pixels * bytes_per_pixel;
73
74 let usize_bytes = usize::try_from(total_bytes).ok()?;
76
77 match self {
78 Self::Unlimited => Some(usize_bytes),
79 Self::Bytes(limit) => {
80 if total_bytes > limit.get() {
81 None
82 } else {
83 Some(usize_bytes)
84 }
85 },
86 }
87 }
88}
89
90#[derive(Clone, Debug)]
92pub struct DecodeOptions {
93 memory_limit: MemoryLimit,
94 color_output: ColorOutput,
95 check_frame_consistency: bool,
96 skip_frame_decoding: bool,
97 check_for_end_code: bool,
98 allow_unknown_blocks: bool,
99}
100
101impl Default for DecodeOptions {
102 fn default() -> Self {
103 Self::new()
104 }
105}
106
107impl DecodeOptions {
108 #[must_use]
110 #[inline]
111 pub fn new() -> Self {
112 Self {
113 memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), color_output: ColorOutput::Indexed,
115 check_frame_consistency: false,
116 skip_frame_decoding: false,
117 check_for_end_code: false,
118 allow_unknown_blocks: false,
119 }
120 }
121
122 #[inline]
124 pub fn set_color_output(&mut self, color: ColorOutput) {
125 self.color_output = color;
126 }
127
128 pub fn set_memory_limit(&mut self, limit: MemoryLimit) {
130 self.memory_limit = limit;
131 }
132
133 pub fn check_frame_consistency(&mut self, check: bool) {
144 self.check_frame_consistency = check;
145 }
146
147 pub fn skip_frame_decoding(&mut self, skip: bool) {
156 self.skip_frame_decoding = skip;
157 }
158
159 pub fn check_lzw_end_code(&mut self, check: bool) {
171 self.check_for_end_code = check;
172 }
173
174 pub fn allow_unknown_blocks(&mut self, check: bool) {
190 self.allow_unknown_blocks = check;
191 }
192
193 pub fn read_info<R: Read>(self, r: R) -> Result<Decoder<R>, DecodingError> {
197 Decoder::with_no_init(r, StreamingDecoder::with_options(&self), self).init()
198 }
199}
200
201struct ReadDecoder<R: Read> {
202 reader: io::BufReader<R>,
203 decoder: StreamingDecoder,
204 at_eof: bool,
205}
206
207impl<R: Read> ReadDecoder<R> {
208 #[inline(never)]
209 fn decode_next(&mut self, write_into: &mut OutputBuffer<'_>) -> Result<Option<Decoded>, DecodingError> {
210 while !self.at_eof {
211 let (consumed, result) = {
212 let buf = self.reader.fill_buf()?;
213 if buf.is_empty() {
214 return Err(io::ErrorKind::UnexpectedEof.into());
215 }
216
217 self.decoder.update(buf, write_into)?
218 };
219 self.reader.consume(consumed);
220 match result {
221 Decoded::Nothing => (),
222 Decoded::BlockStart(Block::Trailer) => {
223 self.at_eof = true;
224 },
225 result => return Ok(Some(result)),
226 }
227 }
228 Ok(None)
229 }
230
231 fn into_inner(self) -> io::BufReader<R> {
232 self.reader
233 }
234
235 fn decode_next_bytes(&mut self, out: &mut OutputBuffer<'_>) -> Result<usize, DecodingError> {
236 match self.decode_next(out)? {
237 Some(Decoded::BytesDecoded(len)) => Ok(len.get()),
238 Some(Decoded::DataEnd) => Ok(0),
239 _ => Err(DecodingError::format("unexpected data")),
240 }
241 }
242}
243
244#[allow(dead_code)]
245pub struct Decoder<R: Read> {
247 decoder: ReadDecoder<R>,
248 pixel_converter: PixelConverter,
249 bg_color: Option<u8>,
250 repeat: Repeat,
251 current_frame: Frame<'static>,
252 current_frame_data_type: FrameDataType,
253}
254
255impl<R> Decoder<R> where R: Read {
256 #[inline]
258 pub fn new(reader: R) -> Result<Self, DecodingError> {
259 DecodeOptions::new().read_info(reader)
260 }
261
262 #[must_use]
264 #[inline]
265 pub fn build() -> DecodeOptions {
266 DecodeOptions::new()
267 }
268
269 fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Self {
270 Self {
271 decoder: ReadDecoder {
272 reader: io::BufReader::new(reader),
273 decoder,
274 at_eof: false,
275 },
276 bg_color: None,
277 pixel_converter: PixelConverter::new(options.color_output, options.memory_limit),
278 repeat: Repeat::default(),
279 current_frame: Frame::default(),
280 current_frame_data_type: FrameDataType::Pixels,
281 }
282 }
283
284 fn init(mut self) -> Result<Self, DecodingError> {
285 loop {
286 match self.decoder.decode_next(&mut OutputBuffer::None)? {
287 Some(Decoded::BackgroundColor(bg_color)) => {
288 self.bg_color = Some(bg_color);
289 }
290 Some(Decoded::GlobalPalette(palette)) => {
291 self.pixel_converter.set_global_palette(palette.into());
292 },
293 Some(Decoded::Repetitions(repeat)) => {
294 self.repeat = repeat;
295 },
296 Some(Decoded::HeaderEnd) => break,
297 Some(_) => {
298 continue;
300 },
301 None => return Err(DecodingError::format(
302 "file does not contain any image data"
303 ))
304 }
305 }
306 if let Some(palette) = self.pixel_converter.global_palette() {
308 if self.bg_color.unwrap_or(0) as usize >= (palette.len() / PLTE_CHANNELS) {
309 self.bg_color = None;
310 }
311 }
312 Ok(self)
313 }
314
315 pub fn next_frame_info(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
317 loop {
318 match self.decoder.decode_next(&mut OutputBuffer::None)? {
319 Some(Decoded::FrameMetadata(frame_data_type)) => {
320 self.current_frame = self.decoder.decoder.current_frame_mut().take();
321 self.current_frame_data_type = frame_data_type;
322 if self.current_frame.palette.is_none() && self.global_palette().is_none() {
323 return Err(DecodingError::format(
324 "no color table available for current frame",
325 ));
326 }
327 break;
328 }
329 Some(_) => (),
330 None => return Ok(None),
331 }
332 }
333 Ok(Some(&self.current_frame))
334 }
335
336 pub fn read_next_frame(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> {
343 if self.next_frame_info()?.is_some() {
344 match self.current_frame_data_type {
345 FrameDataType::Pixels => {
346 self.pixel_converter.read_frame(&mut self.current_frame, &mut |out| self.decoder.decode_next_bytes(out))?;
347 },
348 FrameDataType::Lzw { min_code_size } => {
349 let mut vec = if matches!(self.current_frame.buffer, Cow::Owned(_)) {
350 let mut vec = mem::replace(&mut self.current_frame.buffer, Cow::Borrowed(&[])).into_owned();
351 vec.clear();
352 vec
353 } else {
354 Vec::new()
355 };
356 vec.try_reserve(usize::from(self.current_frame.width) * usize::from(self.current_frame.height) / 4)
358 .map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
359 self.copy_lzw_into_buffer(min_code_size, &mut vec)?;
360 self.current_frame.buffer = Cow::Owned(vec);
361 },
362 }
363 Ok(Some(&self.current_frame))
364 } else {
365 Ok(None)
366 }
367 }
368
369 fn take_current_frame(&mut self) -> Option<Frame<'static>> {
371 if self.current_frame.buffer.is_empty() {
372 return None;
373 }
374 Some(self.current_frame.take())
375 }
376
377 pub fn read_into_buffer(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> {
383 self.pixel_converter.read_into_buffer(&self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out))
384 }
385
386 fn copy_lzw_into_buffer(&mut self, min_code_size: u8, buf: &mut Vec<u8>) -> Result<(), DecodingError> {
387 buf.push(min_code_size);
389 loop {
390 match self.decoder.decode_next(&mut OutputBuffer::Vec(buf))? {
391 Some(Decoded::LzwDataCopied(_len)) => {},
392 Some(Decoded::DataEnd) => return Ok(()),
393 _ => return Err(DecodingError::format("unexpected data")),
394 }
395 }
396 }
397
398 pub fn fill_buffer(&mut self, buf: &mut [u8]) -> Result<bool, DecodingError> {
406 self.pixel_converter.fill_buffer(&self.current_frame, buf, &mut |out| self.decoder.decode_next_bytes(out))
407 }
408
409 pub fn buffer_size(&self) -> usize {
411 self.pixel_converter.buffer_size(&self.current_frame).unwrap()
412 }
413
414 pub fn line_length(&self) -> usize {
416 self.pixel_converter.line_length(&self.current_frame)
417 }
418
419 #[inline]
421 pub fn palette(&self) -> Result<&[u8], DecodingError> {
422 Ok(match self.current_frame.palette {
423 Some(ref table) => table,
424 None => self.global_palette().ok_or(DecodingError::format(
425 "no color table available for current frame",
426 ))?,
427 })
428 }
429
430 pub fn global_palette(&self) -> Option<&[u8]> {
432 self.pixel_converter.global_palette()
433 }
434
435 #[inline]
437 pub fn width(&self) -> u16 {
438 self.decoder.decoder.width()
439 }
440
441 #[inline]
443 pub fn height(&self) -> u16 {
444 self.decoder.decoder.height()
445 }
446
447 pub fn into_inner(self) -> io::BufReader<R> {
449 self.decoder.into_inner()
450 }
451
452 pub fn bg_color(&self) -> Option<usize> {
457 self.bg_color.map(|v| v as usize)
458 }
459
460 #[inline]
462 pub fn repeat(&self) -> Repeat {
463 self.repeat
464 }
465}
466
467impl<R: Read> IntoIterator for Decoder<R> {
468 type Item = Result<Frame<'static>, DecodingError>;
469 type IntoIter = DecoderIter<R>;
470
471 #[inline]
472 fn into_iter(self) -> Self::IntoIter {
473 DecoderIter {
474 inner: self,
475 ended: false,
476 }
477 }
478}
479
480pub struct DecoderIter<R: Read> {
482 inner: Decoder<R>,
483 ended: bool,
484}
485
486impl<R: Read> DecoderIter<R> {
487 pub fn into_inner(self) -> io::BufReader<R> {
491 self.inner.into_inner()
492 }
493}
494
495impl<R: Read> FusedIterator for DecoderIter<R> {}
496
497impl<R: Read> Iterator for DecoderIter<R> {
498 type Item = Result<Frame<'static>, DecodingError>;
499
500 fn next(&mut self) -> Option<Self::Item> {
501 if !self.ended {
502 match self.inner.read_next_frame() {
503 Ok(Some(_)) => self.inner.take_current_frame().map(Ok),
504 Ok(None) => {
505 self.ended = true;
506 None
507 },
508 Err(err) => {
509 self.ended = true;
510 Some(Err(err))
511 },
512 }
513 } else {
514 None
515 }
516 }
517}