png/decoder/
mod.rs

1mod interlace_info;
2mod read_decoder;
3pub(crate) mod stream;
4pub(crate) mod transform;
5mod unfiltering_buffer;
6mod zlib;
7
8use self::read_decoder::{ImageDataCompletionStatus, ReadDecoder};
9use self::stream::{DecodeOptions, DecodingError, FormatErrorInner, CHUNK_BUFFER_SIZE};
10use self::transform::{create_transform_fn, TransformFn};
11use self::unfiltering_buffer::UnfilteringBuffer;
12
13use std::io::Read;
14use std::mem;
15
16use crate::adam7::{self, Adam7Info};
17use crate::common::{
18    BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations,
19};
20use crate::FrameControl;
21
22pub use interlace_info::InterlaceInfo;
23use interlace_info::InterlaceInfoIter;
24
25/*
26pub enum InterlaceHandling {
27    /// Outputs the raw rows
28    RawRows,
29    /// Fill missing the pixels from the existing ones
30    Rectangle,
31    /// Only fill the needed pixels
32    Sparkle
33}
34*/
35
36/// Output info.
37///
38/// This describes one particular frame of the image that was written into the output buffer.
39#[derive(Debug, PartialEq, Eq)]
40pub struct OutputInfo {
41    /// The pixel width of this frame.
42    pub width: u32,
43    /// The pixel height of this frame.
44    pub height: u32,
45    /// The chosen output color type.
46    pub color_type: ColorType,
47    /// The chosen output bit depth.
48    pub bit_depth: BitDepth,
49    /// The byte count of each scan line in the image.
50    pub line_size: usize,
51}
52
53impl OutputInfo {
54    /// Returns the size needed to hold a decoded frame
55    /// If the output buffer was larger then bytes after this count should be ignored. They may
56    /// still have been changed.
57    pub fn buffer_size(&self) -> usize {
58        self.line_size * self.height as usize
59    }
60}
61
62#[derive(Clone, Copy, Debug)]
63/// Limits on the resources the `Decoder` is allowed too use
64pub struct Limits {
65    /// maximum number of bytes the decoder is allowed to allocate, default is 64Mib
66    pub bytes: usize,
67}
68
69impl Limits {
70    pub(crate) fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> {
71        if self.bytes >= bytes {
72            self.bytes -= bytes;
73            Ok(())
74        } else {
75            Err(DecodingError::LimitsExceeded)
76        }
77    }
78}
79
80impl Default for Limits {
81    fn default() -> Limits {
82        Limits {
83            bytes: 1024 * 1024 * 64,
84        }
85    }
86}
87
88/// PNG Decoder
89pub struct Decoder<R: Read> {
90    read_decoder: ReadDecoder<R>,
91    /// Output transformations
92    transform: Transformations,
93}
94
95/// A row of data with interlace information attached.
96#[derive(Clone, Copy, Debug)]
97pub struct InterlacedRow<'data> {
98    data: &'data [u8],
99    interlace: InterlaceInfo,
100}
101
102impl<'data> InterlacedRow<'data> {
103    pub fn data(&self) -> &'data [u8] {
104        self.data
105    }
106
107    pub fn interlace(&self) -> &InterlaceInfo {
108        &self.interlace
109    }
110}
111
112/// A row of data without interlace information.
113#[derive(Clone, Copy, Debug)]
114pub struct Row<'data> {
115    data: &'data [u8],
116}
117
118impl<'data> Row<'data> {
119    pub fn data(&self) -> &'data [u8] {
120        self.data
121    }
122}
123
124impl<R: Read> Decoder<R> {
125    /// Create a new decoder configuration with default limits.
126    pub fn new(r: R) -> Decoder<R> {
127        Decoder::new_with_limits(r, Limits::default())
128    }
129
130    /// Create a new decoder configuration with custom limits.
131    pub fn new_with_limits(r: R, limits: Limits) -> Decoder<R> {
132        let mut read_decoder = ReadDecoder::new(r);
133        read_decoder.set_limits(limits);
134
135        Decoder {
136            read_decoder,
137            transform: Transformations::IDENTITY,
138        }
139    }
140
141    /// Create a new decoder configuration with custom `DecodeOptions`.
142    pub fn new_with_options(r: R, decode_options: DecodeOptions) -> Decoder<R> {
143        let mut read_decoder = ReadDecoder::with_options(r, decode_options);
144        read_decoder.set_limits(Limits::default());
145
146        Decoder {
147            read_decoder,
148            transform: Transformations::IDENTITY,
149        }
150    }
151
152    /// Limit resource usage.
153    ///
154    /// Note that your allocations, e.g. when reading into a pre-allocated buffer, are __NOT__
155    /// considered part of the limits. Nevertheless, required intermediate buffers such as for
156    /// singular lines is checked against the limit.
157    ///
158    /// Note that this is a best-effort basis.
159    ///
160    /// ```
161    /// use std::fs::File;
162    /// use png::{Decoder, Limits};
163    /// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes.
164    /// let mut limits = Limits::default();
165    /// limits.bytes = 3;
166    /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
167    /// assert!(decoder.read_info().is_err());
168    ///
169    /// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
170    /// let mut limits = Limits::default();
171    /// limits.bytes = 10*1024;
172    /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
173    /// assert!(decoder.read_info().is_ok());
174    /// ```
175    pub fn set_limits(&mut self, limits: Limits) {
176        self.read_decoder.set_limits(limits);
177    }
178
179    /// Read the PNG header and return the information contained within.
180    ///
181    /// Most image metadata will not be read until `read_info` is called, so those fields will be
182    /// None or empty.
183    pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> {
184        self.read_decoder.read_header_info()
185    }
186
187    /// Reads all meta data until the first IDAT chunk
188    pub fn read_info(mut self) -> Result<Reader<R>, DecodingError> {
189        self.read_header_info()?;
190
191        let mut reader = Reader {
192            decoder: self.read_decoder,
193            bpp: BytesPerPixel::One,
194            subframe: SubframeInfo::not_yet_init(),
195            remaining_frames: 0, // Temporary value - fixed below after reading `acTL` and `fcTL`.
196            unfiltering_buffer: UnfilteringBuffer::new(),
197            transform: self.transform,
198            transform_fn: None,
199            scratch_buffer: Vec::new(),
200            finished: false,
201        };
202
203        // Check if the decoding buffer of a single raw line has a valid size.
204        if reader.info().checked_raw_row_length().is_none() {
205            return Err(DecodingError::LimitsExceeded);
206        }
207
208        // Check if the output buffer has a valid size.
209        let (width, height) = reader.info().size();
210        let (color, depth) = reader.output_color_type();
211        let rowlen = color
212            .checked_raw_row_length(depth, width)
213            .ok_or(DecodingError::LimitsExceeded)?
214            - 1;
215        let height: usize =
216            std::convert::TryFrom::try_from(height).map_err(|_| DecodingError::LimitsExceeded)?;
217        if rowlen.checked_mul(height).is_none() {
218            return Err(DecodingError::LimitsExceeded);
219        }
220
221        reader.read_until_image_data()?;
222
223        reader.remaining_frames = match reader.info().animation_control.as_ref() {
224            None => 1, // No `acTL` => only expecting `IDAT` frame.
225            Some(animation) => {
226                let mut num_frames = animation.num_frames as usize;
227                if reader.info().frame_control.is_none() {
228                    // No `fcTL` before `IDAT` => `IDAT` is not part of the animation, but
229                    // represents an *extra*, default frame for non-APNG-aware decoders.
230                    num_frames += 1;
231                }
232                num_frames
233            }
234        };
235        Ok(reader)
236    }
237
238    /// Set the allowed and performed transformations.
239    ///
240    /// A transformation is a pre-processing on the raw image data modifying content or encoding.
241    /// Many options have an impact on memory or CPU usage during decoding.
242    pub fn set_transformations(&mut self, transform: Transformations) {
243        self.transform = transform;
244    }
245
246    /// Set the decoder to ignore all text chunks while parsing.
247    ///
248    /// eg.
249    /// ```
250    /// use std::fs::File;
251    /// use png::Decoder;
252    /// let mut decoder = Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap());
253    /// decoder.set_ignore_text_chunk(true);
254    /// assert!(decoder.read_info().is_ok());
255    /// ```
256    pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
257        self.read_decoder.set_ignore_text_chunk(ignore_text_chunk);
258    }
259
260    /// Set the decoder to ignore iccp chunks while parsing.
261    ///
262    /// eg.
263    /// ```
264    /// use std::fs::File;
265    /// use png::Decoder;
266    /// let mut decoder = Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
267    /// decoder.set_ignore_iccp_chunk(true);
268    /// assert!(decoder.read_info().is_ok());
269    /// ```
270    pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
271        self.read_decoder.set_ignore_iccp_chunk(ignore_iccp_chunk);
272    }
273
274    /// Set the decoder to ignore and not verify the Adler-32 checksum
275    /// and CRC code.
276    pub fn ignore_checksums(&mut self, ignore_checksums: bool) {
277        self.read_decoder.ignore_checksums(ignore_checksums);
278    }
279}
280
281/// PNG reader (mostly high-level interface)
282///
283/// Provides a high level that iterates over lines or whole images.
284pub struct Reader<R: Read> {
285    decoder: ReadDecoder<R>,
286    bpp: BytesPerPixel,
287    subframe: SubframeInfo,
288    /// How many frames remain to be decoded.  Decremented after each `IDAT` or `fdAT` sequence.
289    remaining_frames: usize,
290    /// Buffer with not-yet-`unfilter`-ed image rows
291    unfiltering_buffer: UnfilteringBuffer,
292    /// Output transformations
293    transform: Transformations,
294    /// Function that can transform decompressed, unfiltered rows into final output.
295    /// See the `transform.rs` module for more details.
296    transform_fn: Option<TransformFn>,
297    /// This buffer is only used so that `next_row` and `next_interlaced_row` can return reference
298    /// to a byte slice. In a future version of this library, this buffer will be removed and
299    /// `next_row` and `next_interlaced_row` will write directly into a user provided output buffer.
300    scratch_buffer: Vec<u8>,
301    /// Whether `ImageEnd` was already reached by `fn finish`.
302    finished: bool,
303}
304
305/// The subframe specific information.
306///
307/// In APNG the frames are constructed by combining previous frame and a new subframe (through a
308/// combination of `dispose_op` and `overlay_op`). These sub frames specify individual dimension
309/// information and reuse the global interlace options. This struct encapsulates the state of where
310/// in a particular IDAT-frame or subframe we are.
311struct SubframeInfo {
312    width: u32,
313    height: u32,
314    rowlen: usize,
315    current_interlace_info: Option<InterlaceInfo>,
316    interlace_info_iter: InterlaceInfoIter,
317    consumed_and_flushed: bool,
318}
319
320impl<R: Read> Reader<R> {
321    /// Advances to the start of the next animation frame and
322    /// returns a reference to the `FrameControl` info that describes it.
323    /// Skips and discards the image data of the previous frame if necessary.
324    ///
325    /// Returns a [`ParameterError`] when there are no more animation frames.
326    /// To avoid this the caller can check if [`Info::animation_control`] exists
327    /// and consult [`AnimationControl::num_frames`].
328    pub fn next_frame_info(&mut self) -> Result<&FrameControl, DecodingError> {
329        let remaining_frames = if self.subframe.consumed_and_flushed {
330            self.remaining_frames
331        } else {
332            // One remaining frame will be consumed by the `finish_decoding` call below.
333            self.remaining_frames - 1
334        };
335        if remaining_frames == 0 {
336            return Err(DecodingError::Parameter(
337                ParameterErrorKind::PolledAfterEndOfImage.into(),
338            ));
339        }
340
341        if !self.subframe.consumed_and_flushed {
342            self.subframe.current_interlace_info = None;
343            self.finish_decoding()?;
344        }
345        self.read_until_image_data()?;
346
347        // The PNG standard (and `StreamingDecoder `) guarantes that there is an `fcTL` chunk
348        // before the start of image data in a sequence of `fdAT` chunks.  Therefore `unwrap`
349        // below is guaranteed to not panic.
350        Ok(self.info().frame_control.as_ref().unwrap())
351    }
352
353    /// Reads all meta data until the next frame data starts.
354    /// Requires IHDR before the IDAT and fcTL before fdAT.
355    fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
356        self.decoder.read_until_image_data()?;
357
358        self.subframe = SubframeInfo::new(self.info());
359        self.bpp = self.info().bpp_in_prediction();
360        self.unfiltering_buffer = UnfilteringBuffer::new();
361
362        // Allocate output buffer.
363        let buflen = self.output_line_size(self.subframe.width);
364        self.decoder.reserve_bytes(buflen)?;
365
366        Ok(())
367    }
368
369    /// Get information on the image.
370    ///
371    /// The structure will change as new frames of an animated image are decoded.
372    pub fn info(&self) -> &Info<'static> {
373        self.decoder.info().unwrap()
374    }
375
376    /// Decodes the next frame into `buf`.
377    ///
378    /// Note that this decodes raw subframes that need to be mixed according to blend-op and
379    /// dispose-op by the caller.
380    ///
381    /// The caller must always provide a buffer large enough to hold a complete frame (the APNG
382    /// specification restricts subframes to the dimensions given in the image header). The region
383    /// that has been written be checked afterwards by calling `info` after a successful call and
384    /// inspecting the `frame_control` data. This requirement may be lifted in a later version of
385    /// `png`.
386    ///
387    /// Output lines will be written in row-major, packed matrix with width and height of the read
388    /// frame (or subframe), all samples are in big endian byte order where this matters.
389    pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<OutputInfo, DecodingError> {
390        if self.remaining_frames == 0 {
391            return Err(DecodingError::Parameter(
392                ParameterErrorKind::PolledAfterEndOfImage.into(),
393            ));
394        } else if self.subframe.consumed_and_flushed {
395            // Advance until the next `fdAT`
396            // (along the way we should encounter the fcTL for this frame).
397            self.read_until_image_data()?;
398        }
399
400        if buf.len() < self.output_buffer_size() {
401            return Err(DecodingError::Parameter(
402                ParameterErrorKind::ImageBufferSize {
403                    expected: buf.len(),
404                    actual: self.output_buffer_size(),
405                }
406                .into(),
407            ));
408        }
409
410        let (color_type, bit_depth) = self.output_color_type();
411        let output_info = OutputInfo {
412            width: self.subframe.width,
413            height: self.subframe.height,
414            color_type,
415            bit_depth,
416            line_size: self.output_line_size(self.subframe.width),
417        };
418
419        if self.info().interlaced {
420            let stride = self.output_line_size(self.info().width);
421            let samples = color_type.samples() as u8;
422            let bits_pp = samples * (bit_depth as u8);
423            while let Some(InterlacedRow {
424                data: row,
425                interlace,
426                ..
427            }) = self.next_interlaced_row()?
428            {
429                // `unwrap` won't panic, because we checked `self.info().interlaced` above.
430                let adam7info = interlace.get_adam7_info().unwrap();
431                adam7::expand_pass(buf, stride, row, adam7info, bits_pp);
432            }
433        } else {
434            let current_interlace_info = self.subframe.current_interlace_info.as_ref();
435            let already_done_rows = current_interlace_info
436                .map(|info| info.line_number())
437                .unwrap_or(self.subframe.height);
438
439            for row in buf
440                .chunks_exact_mut(output_info.line_size)
441                .take(self.subframe.height as usize)
442                .skip(already_done_rows as usize)
443            {
444                self.next_interlaced_row_impl(self.subframe.rowlen, row)?;
445            }
446        }
447
448        // Advance over the rest of data for this (sub-)frame.
449        self.finish_decoding()?;
450
451        Ok(output_info)
452    }
453
454    fn mark_subframe_as_consumed_and_flushed(&mut self) {
455        assert!(self.remaining_frames > 0);
456        self.remaining_frames -= 1;
457
458        self.subframe.consumed_and_flushed = true;
459    }
460
461    /// Advance over the rest of data for this (sub-)frame.
462    /// Called after decoding the last row of a frame.
463    fn finish_decoding(&mut self) -> Result<(), DecodingError> {
464        // Double-check that all rows of this frame have been decoded (i.e. that the potential
465        // `finish_decoding` call below won't be discarding any data).
466        assert!(self.subframe.current_interlace_info.is_none());
467
468        // Discard the remaining data in the current sequence of `IDAT` or `fdAT` chunks.
469        if !self.subframe.consumed_and_flushed {
470            self.decoder.finish_decoding_image_data()?;
471            self.mark_subframe_as_consumed_and_flushed();
472        }
473
474        Ok(())
475    }
476
477    /// Returns the next processed row of the image
478    pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
479        self.next_interlaced_row()
480            .map(|v| v.map(|v| Row { data: v.data }))
481    }
482
483    /// Returns the next processed row of the image
484    pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
485        let interlace = match self.subframe.current_interlace_info.as_ref() {
486            None => {
487                self.finish_decoding()?;
488                return Ok(None);
489            }
490            Some(interlace) => *interlace,
491        };
492        if interlace.line_number() == 0 {
493            self.unfiltering_buffer.reset_prev_row();
494        }
495        let rowlen = match interlace {
496            InterlaceInfo::Null(_) => self.subframe.rowlen,
497            InterlaceInfo::Adam7(Adam7Info { width, .. }) => {
498                self.info().raw_row_length_from_width(width)
499            }
500        };
501        let width = match interlace {
502            InterlaceInfo::Adam7(Adam7Info { width, .. }) => width,
503            InterlaceInfo::Null(_) => self.subframe.width,
504        };
505        let output_line_size = self.output_line_size(width);
506
507        // TODO: change the interface of `next_interlaced_row` to take an output buffer instead of
508        // making us return a reference to a buffer that we own.
509        let mut output_buffer = mem::take(&mut self.scratch_buffer);
510        output_buffer.resize(output_line_size, 0u8);
511        let ret = self.next_interlaced_row_impl(rowlen, &mut output_buffer);
512        self.scratch_buffer = output_buffer;
513        ret?;
514
515        Ok(Some(InterlacedRow {
516            data: &self.scratch_buffer[..output_line_size],
517            interlace,
518        }))
519    }
520
521    /// Read the rest of the image and chunks and finish up, including text chunks or others
522    /// This will discard the rest of the image if the image is not read already with [`Reader::next_frame`], [`Reader::next_row`] or [`Reader::next_interlaced_row`]
523    pub fn finish(&mut self) -> Result<(), DecodingError> {
524        if self.finished {
525            return Err(DecodingError::Parameter(
526                ParameterErrorKind::PolledAfterEndOfImage.into(),
527            ));
528        }
529
530        self.remaining_frames = 0;
531        self.unfiltering_buffer = UnfilteringBuffer::new();
532        self.decoder.read_until_end_of_input()?;
533
534        self.finished = true;
535        Ok(())
536    }
537
538    /// Fetch the next interlaced row and filter it according to our own transformations.
539    fn next_interlaced_row_impl(
540        &mut self,
541        rowlen: usize,
542        output_buffer: &mut [u8],
543    ) -> Result<(), DecodingError> {
544        self.next_raw_interlaced_row(rowlen)?;
545        let row = self.unfiltering_buffer.prev_row();
546        assert_eq!(row.len(), rowlen - 1);
547
548        // Apply transformations and write resulting data to buffer.
549        let transform_fn = {
550            if self.transform_fn.is_none() {
551                self.transform_fn = Some(create_transform_fn(self.info(), self.transform)?);
552            }
553            self.transform_fn.as_deref().unwrap()
554        };
555        transform_fn(row, output_buffer, self.info());
556
557        self.subframe.current_interlace_info = self.subframe.interlace_info_iter.next();
558        Ok(())
559    }
560
561    /// Returns the color type and the number of bits per sample
562    /// of the data returned by `Reader::next_row` and Reader::frames`.
563    pub fn output_color_type(&self) -> (ColorType, BitDepth) {
564        use crate::common::ColorType::*;
565        let t = self.transform;
566        let info = self.info();
567        if t == Transformations::IDENTITY {
568            (info.color_type, info.bit_depth)
569        } else {
570            let bits = match info.bit_depth as u8 {
571                16 if t.intersects(Transformations::STRIP_16) => 8,
572                n if n < 8
573                    && (t.contains(Transformations::EXPAND)
574                        || t.contains(Transformations::ALPHA)) =>
575                {
576                    8
577                }
578                n => n,
579            };
580            let color_type =
581                if t.contains(Transformations::EXPAND) || t.contains(Transformations::ALPHA) {
582                    let has_trns = info.trns.is_some() || t.contains(Transformations::ALPHA);
583                    match info.color_type {
584                        Grayscale if has_trns => GrayscaleAlpha,
585                        Rgb if has_trns => Rgba,
586                        Indexed if has_trns => Rgba,
587                        Indexed => Rgb,
588                        ct => ct,
589                    }
590                } else {
591                    info.color_type
592                };
593            (color_type, BitDepth::from_u8(bits).unwrap())
594        }
595    }
596
597    /// Returns the number of bytes required to hold a deinterlaced image frame
598    /// that is decoded using the given input transformations.
599    pub fn output_buffer_size(&self) -> usize {
600        let (width, height) = self.info().size();
601        let size = self.output_line_size(width);
602        size * height as usize
603    }
604
605    /// Returns the number of bytes required to hold a deinterlaced row.
606    pub fn output_line_size(&self, width: u32) -> usize {
607        let (color, depth) = self.output_color_type();
608        color.raw_row_length_from_width(depth, width) - 1
609    }
610
611    /// Unfilter the next raw interlaced row into `self.unfiltering_buffer`.
612    fn next_raw_interlaced_row(&mut self, rowlen: usize) -> Result<(), DecodingError> {
613        // Read image data until we have at least one full row (but possibly more than one).
614        while self.unfiltering_buffer.curr_row_len() < rowlen {
615            if self.subframe.consumed_and_flushed {
616                return Err(DecodingError::Format(
617                    FormatErrorInner::NoMoreImageData.into(),
618                ));
619            }
620
621            match self
622                .decoder
623                .decode_image_data(self.unfiltering_buffer.as_mut_vec())?
624            {
625                ImageDataCompletionStatus::ExpectingMoreData => (),
626                ImageDataCompletionStatus::Done => self.mark_subframe_as_consumed_and_flushed(),
627            }
628        }
629
630        self.unfiltering_buffer.unfilter_curr_row(rowlen, self.bpp)
631    }
632}
633
634impl SubframeInfo {
635    fn not_yet_init() -> Self {
636        SubframeInfo {
637            width: 0,
638            height: 0,
639            rowlen: 0,
640            current_interlace_info: None,
641            interlace_info_iter: InterlaceInfoIter::empty(),
642            consumed_and_flushed: false,
643        }
644    }
645
646    fn new(info: &Info) -> Self {
647        // The apng fctnl overrides width and height.
648        // All other data is set by the main info struct.
649        let (width, height) = if let Some(fc) = info.frame_control {
650            (fc.width, fc.height)
651        } else {
652            (info.width, info.height)
653        };
654
655        let mut interlace_info_iter = InterlaceInfoIter::new(width, height, info.interlaced);
656        let current_interlace_info = interlace_info_iter.next();
657        SubframeInfo {
658            width,
659            height,
660            rowlen: info.raw_row_length_from_width(width),
661            current_interlace_info,
662            interlace_info_iter,
663            consumed_and_flushed: false,
664        }
665    }
666}