gif/reader/
mod.rs

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)]
25/// The maximum amount of memory the decoder is allowed to use for each frame
26pub enum MemoryLimit {
27    /// Enforce no memory limit.
28    ///
29    /// If you intend to process images from unknown origins this is a potentially dangerous
30    /// constant to use, as your program could be vulnerable to decompression bombs. That is,
31    /// malicious images crafted specifically to require an enormous amount of memory to process
32    /// while having a disproportionately small file size.
33    ///
34    /// The risks for modern machines are a bit smaller as the size of each frame cannot
35    /// exceed 16GiB, but this is still a significant amount of memory.
36    Unlimited,
37    /// Limit the amount of memory that can be used for a single frame to this many bytes.
38    ///
39    /// It may not be enforced precisely due to allocator overhead
40    /// and the decoder potentially allocating small auxiliary buffers,
41    /// but it will precisely limit the size of the output buffer for each frame.
42    //
43    // The `NonZero` type is used to make FFI simpler.
44    // Due to the guaranteed niche optimization, `Unlimited` will be represented as `0`,
45    // and the whole enum as a simple `u64`.
46    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        // This cannot overflow because the maximum possible value is 16GiB, well within u64 range
72        let total_bytes = pixels * bytes_per_pixel;
73
74        // On 32-bit platforms the size of the output buffer may not be representable
75        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/// Options for opening a GIF decoder. [`DecodeOptions::read_info`] will start the decoder.
91#[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    /// Creates a new decoder builder
109    #[must_use]
110    #[inline]
111    pub fn new() -> Self {
112        Self {
113            memory_limit: MemoryLimit::Bytes(50_000_000.try_into().unwrap()), // 50 MB
114            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    /// Configure how color data is decoded.
123    #[inline]
124    pub fn set_color_output(&mut self, color: ColorOutput) {
125        self.color_output = color;
126    }
127
128    /// Configure a memory limit for decoding.
129    pub fn set_memory_limit(&mut self, limit: MemoryLimit) {
130        self.memory_limit = limit;
131    }
132
133    /// Configure if frames must be within the screen descriptor.
134    ///
135    /// The default is `false`.
136    ///
137    /// When turned on, all frame descriptors being read must fit within the screen descriptor or
138    /// otherwise an error is returned and the stream left in an unspecified state.
139    ///
140    /// When turned off, frames may be arbitrarily larger or offset in relation to the screen. Many
141    /// other decoder libraries handle this in highly divergent ways. This moves all checks to the
142    /// caller, for example to emulate a specific style.
143    pub fn check_frame_consistency(&mut self, check: bool) {
144        self.check_frame_consistency = check;
145    }
146
147    /// Configure whether to skip decoding frames.
148    ///
149    /// The default is false.
150    ///
151    /// When turned on, LZW decoding is skipped. [`Decoder::read_next_frame`] will return
152    /// compressed LZW bytes in frame's data.
153    /// [`Decoder::next_frame_info`] will return the metadata of the next frame as usual.
154    /// This is useful to count frames without incurring the overhead of decoding.
155    pub fn skip_frame_decoding(&mut self, skip: bool) {
156        self.skip_frame_decoding = skip;
157    }
158
159    /// Configure if LZW encoded blocks must end with a marker end code.
160    ///
161    /// The default is `false`.
162    ///
163    /// When turned on, all image data blocks—which are LZW encoded—must contain a special bit
164    /// sequence signalling the end of the data. LZW processing terminates when this code is
165    /// encountered. The specification states that it must be the last code output by the encoder
166    /// for an image.
167    ///
168    /// When turned off then image data blocks can simply end. Note that this might silently ignore
169    /// some bits of the last or second to last byte.
170    pub fn check_lzw_end_code(&mut self, check: bool) {
171        self.check_for_end_code = check;
172    }
173
174    /// Configure if unknown blocks are allowed to be decoded.
175    ///
176    /// The default is `false`.
177    ///
178    /// When turned on, the decoder will allow unknown blocks to be in the
179    /// `BlockStart` position.
180    ///
181    /// When turned off, decoded block starts must mark an `Image`, `Extension`,
182    /// or `Trailer` block. Otherwise, the decoded image will return an error.
183    /// If an unknown block error is returned from decoding, enabling this
184    /// setting may allow for a further state of decoding on the next attempt.
185    ///
186    /// This option also allows unknown extension blocks. The decoder assumes the follow the same
187    /// block layout, i.e. a sequence of zero-length terminated sub-blocks immediately follow the
188    /// extension introducer.
189    pub fn allow_unknown_blocks(&mut self, check: bool) {
190        self.allow_unknown_blocks = check;
191    }
192
193    /// Reads the logical screen descriptor including the global color palette
194    ///
195    /// Returns a [`Decoder`]. All decoder configuration has to be done beforehand.
196    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)]
245/// GIF decoder. Create [`DecodeOptions`] to get started, and call [`DecodeOptions::read_info`].
246pub 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    /// Create a new decoder with default options.
257    #[inline]
258    pub fn new(reader: R) -> Result<Self, DecodingError> {
259        DecodeOptions::new().read_info(reader)
260    }
261
262    /// Return a builder that allows configuring limits etc.
263    #[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                    // There will be extra events when parsing application extension
299                    continue;
300                },
301                None => return Err(DecodingError::format(
302                    "file does not contain any image data"
303                ))
304            }
305        }
306        // If the background color is invalid, ignore it
307        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    /// Returns the next frame info
316    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    /// Reads the next frame from the image.
337    ///
338    /// Do not call `Self::next_frame_info` beforehand.
339    /// Deinterlaces the result.
340    ///
341    /// You can also call `.into_iter()` on the decoder to use it as a regular iterator.
342    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                    // Guesstimate 2bpp
357                    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    /// This is private for iterator's use
370    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    /// Reads the data of the current frame into a pre-allocated buffer.
378    ///
379    /// `Self::next_frame_info` needs to be called beforehand.
380    /// The length of `buf` must be at least `Self::buffer_size`.
381    /// Deinterlaces the result.
382    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        // `write_lzw_pre_encoded_frame` smuggles `min_code_size` in the first byte.
388        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    /// Reads data of the current frame into a pre-allocated buffer until the buffer has been
399    /// filled completely.
400    ///
401    /// The buffer length must be an even number of pixels (multiple of 4 if decoding RGBA).
402    ///
403    /// `Self::next_frame_info` needs to be called beforehand. Returns `true` if the supplied
404    /// buffer could be filled completely. Should not be called after `false` had been returned.
405    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    /// Output buffer size
410    pub fn buffer_size(&self) -> usize {
411        self.pixel_converter.buffer_size(&self.current_frame).unwrap()
412    }
413
414    /// Line length of the current frame
415    pub fn line_length(&self) -> usize {
416        self.pixel_converter.line_length(&self.current_frame)
417    }
418
419    /// Returns the color palette relevant for the frame that has been decoded
420    #[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    /// The global color palette
431    pub fn global_palette(&self) -> Option<&[u8]> {
432        self.pixel_converter.global_palette()
433    }
434
435    /// Width of the image
436    #[inline]
437    pub fn width(&self) -> u16 {
438        self.decoder.decoder.width()
439    }
440
441    /// Height of the image
442    #[inline]
443    pub fn height(&self) -> u16 {
444        self.decoder.decoder.height()
445    }
446
447    /// Abort decoding and recover the `io::Read` instance
448    pub fn into_inner(self) -> io::BufReader<R> {
449        self.decoder.into_inner()
450    }
451
452    /// Index of the background color in the global palette
453    ///
454    /// In practice this is not used, and the background is
455    /// always transparent
456    pub fn bg_color(&self) -> Option<usize> {
457        self.bg_color.map(|v| v as usize)
458    }
459
460    /// Number of loop repetitions
461    #[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
480/// Use `decoder.into_iter()` to iterate over the frames
481pub struct DecoderIter<R: Read> {
482    inner: Decoder<R>,
483    ended: bool,
484}
485
486impl<R: Read> DecoderIter<R> {
487    /// Abort decoding and recover the `io::Read` instance
488    ///
489    /// Use `for frame in iter.by_ref()` to be able to call this afterwards.
490    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}