1mod stream;
2pub(crate) mod transform;
3mod zlib;
4
5pub use self::stream::{DecodeOptions, Decoded, DecodingError, StreamingDecoder};
6use self::stream::{FormatErrorInner, CHUNCK_BUFFER_SIZE};
7use self::transform::{create_transform_fn, TransformFn};
8
9use std::io::{BufRead, BufReader, Read};
10use std::mem;
11use std::ops::Range;
12
13use crate::adam7;
14use crate::chunk;
15use crate::common::{
16 BitDepth, BytesPerPixel, ColorType, Info, ParameterErrorKind, Transformations,
17};
18use crate::filter::{unfilter, FilterType};
19
20/*
21pub enum InterlaceHandling {
22 /// Outputs the raw rows
23 RawRows,
24 /// Fill missing the pixels from the existing ones
25 Rectangle,
26 /// Only fill the needed pixels
27 Sparkle
28}
29*/
30
31/// Output info.
32///
33/// This describes one particular frame of the image that was written into the output buffer.
34#[derive(Debug, PartialEq, Eq)]
35pub struct OutputInfo {
36 /// The pixel width of this frame.
37 pub width: u32,
38 /// The pixel height of this frame.
39 pub height: u32,
40 /// The chosen output color type.
41 pub color_type: ColorType,
42 /// The chosen output bit depth.
43 pub bit_depth: BitDepth,
44 /// The byte count of each scan line in the image.
45 pub line_size: usize,
46}
47
48impl OutputInfo {
49 /// Returns the size needed to hold a decoded frame
50 /// If the output buffer was larger then bytes after this count should be ignored. They may
51 /// still have been changed.
52 pub fn buffer_size(&self) -> usize {
53 self.line_size * self.height as usize
54 }
55}
56
57#[derive(Clone, Copy, Debug)]
58/// Limits on the resources the `Decoder` is allowed too use
59pub struct Limits {
60 /// maximum number of bytes the decoder is allowed to allocate, default is 64Mib
61 pub bytes: usize,
62}
63
64impl Limits {
65 pub(crate) fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> {
66 if self.bytes >= bytes {
67 self.bytes -= bytes;
68 Ok(())
69 } else {
70 Err(DecodingError::LimitsExceeded)
71 }
72 }
73}
74
75impl Default for Limits {
76 fn default() -> Limits {
77 Limits {
78 bytes: 1024 * 1024 * 64,
79 }
80 }
81}
82
83/// PNG Decoder
84pub struct Decoder<R: Read> {
85 read_decoder: ReadDecoder<R>,
86 /// Output transformations
87 transform: Transformations,
88}
89
90/// A row of data with interlace information attached.
91#[derive(Clone, Copy, Debug)]
92pub struct InterlacedRow<'data> {
93 data: &'data [u8],
94 interlace: InterlaceInfo,
95}
96
97impl<'data> InterlacedRow<'data> {
98 pub fn data(&self) -> &'data [u8] {
99 self.data
100 }
101
102 pub fn interlace(&self) -> InterlaceInfo {
103 self.interlace
104 }
105}
106
107/// PNG (2003) specifies two interlace modes, but reserves future extensions.
108#[derive(Clone, Copy, Debug)]
109pub enum InterlaceInfo {
110 /// the null method means no interlacing
111 Null,
112 /// Adam7 derives its name from doing 7 passes over the image, only decoding a subset of all pixels in each pass.
113 /// The following table shows pictorially what parts of each 8x8 area of the image is found in each pass:
114 ///
115 /// 1 6 4 6 2 6 4 6
116 /// 7 7 7 7 7 7 7 7
117 /// 5 6 5 6 5 6 5 6
118 /// 7 7 7 7 7 7 7 7
119 /// 3 6 4 6 3 6 4 6
120 /// 7 7 7 7 7 7 7 7
121 /// 5 6 5 6 5 6 5 6
122 /// 7 7 7 7 7 7 7 7
123 Adam7 { pass: u8, line: u32, width: u32 },
124}
125
126/// A row of data without interlace information.
127#[derive(Clone, Copy, Debug)]
128pub struct Row<'data> {
129 data: &'data [u8],
130}
131
132impl<'data> Row<'data> {
133 pub fn data(&self) -> &'data [u8] {
134 self.data
135 }
136}
137
138impl<R: Read> Decoder<R> {
139 /// Create a new decoder configuration with default limits.
140 pub fn new(r: R) -> Decoder<R> {
141 Decoder::new_with_limits(r, Limits::default())
142 }
143
144 /// Create a new decoder configuration with custom limits.
145 pub fn new_with_limits(r: R, limits: Limits) -> Decoder<R> {
146 let mut decoder = StreamingDecoder::new();
147 decoder.limits = limits;
148
149 Decoder {
150 read_decoder: ReadDecoder {
151 reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r),
152 decoder,
153 at_eof: false,
154 },
155 transform: Transformations::IDENTITY,
156 }
157 }
158
159 /// Create a new decoder configuration with custom `DecodeOptions`.
160 pub fn new_with_options(r: R, decode_options: DecodeOptions) -> Decoder<R> {
161 let mut decoder = StreamingDecoder::new_with_options(decode_options);
162 decoder.limits = Limits::default();
163
164 Decoder {
165 read_decoder: ReadDecoder {
166 reader: BufReader::with_capacity(CHUNCK_BUFFER_SIZE, r),
167 decoder,
168 at_eof: false,
169 },
170 transform: Transformations::IDENTITY,
171 }
172 }
173
174 /// Limit resource usage.
175 ///
176 /// Note that your allocations, e.g. when reading into a pre-allocated buffer, are __NOT__
177 /// considered part of the limits. Nevertheless, required intermediate buffers such as for
178 /// singular lines is checked against the limit.
179 ///
180 /// Note that this is a best-effort basis.
181 ///
182 /// ```
183 /// use std::fs::File;
184 /// use png::{Decoder, Limits};
185 /// // This image is 32×32, 1bit per pixel. The reader buffers one row which requires 4 bytes.
186 /// let mut limits = Limits::default();
187 /// limits.bytes = 3;
188 /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
189 /// assert!(decoder.read_info().is_err());
190 ///
191 /// // This image is 32x32 pixels, so the decoder will allocate less than 10Kib
192 /// let mut limits = Limits::default();
193 /// limits.bytes = 10*1024;
194 /// let mut decoder = Decoder::new_with_limits(File::open("tests/pngsuite/basi0g01.png").unwrap(), limits);
195 /// assert!(decoder.read_info().is_ok());
196 /// ```
197 pub fn set_limits(&mut self, limits: Limits) {
198 self.read_decoder.decoder.limits = limits;
199 }
200
201 /// Read the PNG header and return the information contained within.
202 ///
203 /// Most image metadata will not be read until `read_info` is called, so those fields will be
204 /// None or empty.
205 pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> {
206 let mut buf = Vec::new();
207 while self.read_decoder.info().is_none() {
208 buf.clear();
209 if self.read_decoder.decode_next(&mut buf)?.is_none() {
210 return Err(DecodingError::Format(
211 FormatErrorInner::UnexpectedEof.into(),
212 ));
213 }
214 }
215 Ok(self.read_decoder.info().unwrap())
216 }
217
218 /// Reads all meta data until the first IDAT chunk
219 pub fn read_info(mut self) -> Result<Reader<R>, DecodingError> {
220 self.read_header_info()?;
221
222 let mut reader = Reader {
223 decoder: self.read_decoder,
224 bpp: BytesPerPixel::One,
225 subframe: SubframeInfo::not_yet_init(),
226 fctl_read: 0,
227 next_frame: SubframeIdx::Initial,
228 data_stream: Vec::new(),
229 prev_start: 0,
230 current_start: 0,
231 transform: self.transform,
232 transform_fn: None,
233 scratch_buffer: Vec::new(),
234 };
235
236 // Check if the decoding buffer of a single raw line has a valid size.
237 if reader.info().checked_raw_row_length().is_none() {
238 return Err(DecodingError::LimitsExceeded);
239 }
240
241 // Check if the output buffer has a valid size.
242 let (width, height) = reader.info().size();
243 let (color, depth) = reader.output_color_type();
244 let rowlen = color
245 .checked_raw_row_length(depth, width)
246 .ok_or(DecodingError::LimitsExceeded)?
247 - 1;
248 let height: usize =
249 std::convert::TryFrom::try_from(height).map_err(|_| DecodingError::LimitsExceeded)?;
250 if rowlen.checked_mul(height).is_none() {
251 return Err(DecodingError::LimitsExceeded);
252 }
253
254 reader.read_until_image_data()?;
255 Ok(reader)
256 }
257
258 /// Set the allowed and performed transformations.
259 ///
260 /// A transformation is a pre-processing on the raw image data modifying content or encoding.
261 /// Many options have an impact on memory or CPU usage during decoding.
262 pub fn set_transformations(&mut self, transform: Transformations) {
263 self.transform = transform;
264 }
265
266 /// Set the decoder to ignore all text chunks while parsing.
267 ///
268 /// eg.
269 /// ```
270 /// use std::fs::File;
271 /// use png::Decoder;
272 /// let mut decoder = Decoder::new(File::open("tests/pngsuite/basi0g01.png").unwrap());
273 /// decoder.set_ignore_text_chunk(true);
274 /// assert!(decoder.read_info().is_ok());
275 /// ```
276 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
277 self.read_decoder
278 .decoder
279 .set_ignore_text_chunk(ignore_text_chunk);
280 }
281
282 /// Set the decoder to ignore and not verify the Adler-32 checksum
283 /// and CRC code.
284 pub fn ignore_checksums(&mut self, ignore_checksums: bool) {
285 self.read_decoder
286 .decoder
287 .set_ignore_adler32(ignore_checksums);
288 self.read_decoder.decoder.set_ignore_crc(ignore_checksums);
289 }
290}
291
292struct ReadDecoder<R: Read> {
293 reader: BufReader<R>,
294 decoder: StreamingDecoder,
295 at_eof: bool,
296}
297
298impl<R: Read> ReadDecoder<R> {
299 /// Returns the next decoded chunk. If the chunk is an ImageData chunk, its contents are written
300 /// into image_data.
301 fn decode_next(&mut self, image_data: &mut Vec<u8>) -> Result<Option<Decoded>, DecodingError> {
302 while !self.at_eof {
303 let (consumed, result) = {
304 let buf = self.reader.fill_buf()?;
305 if buf.is_empty() {
306 return Err(DecodingError::Format(
307 FormatErrorInner::UnexpectedEof.into(),
308 ));
309 }
310 self.decoder.update(buf, image_data)?
311 };
312 self.reader.consume(consumed);
313 match result {
314 Decoded::Nothing => (),
315 Decoded::ImageEnd => self.at_eof = true,
316 result => return Ok(Some(result)),
317 }
318 }
319 Ok(None)
320 }
321
322 fn finish_decoding(&mut self) -> Result<(), DecodingError> {
323 while !self.at_eof {
324 let buf = self.reader.fill_buf()?;
325 if buf.is_empty() {
326 return Err(DecodingError::Format(
327 FormatErrorInner::UnexpectedEof.into(),
328 ));
329 }
330 let (consumed, event) = self.decoder.update(buf, &mut vec![])?;
331 self.reader.consume(consumed);
332 match event {
333 Decoded::Nothing => (),
334 Decoded::ImageEnd => self.at_eof = true,
335 // ignore more data
336 Decoded::ChunkComplete(_, _) | Decoded::ChunkBegin(_, _) | Decoded::ImageData => {}
337 Decoded::ImageDataFlushed => return Ok(()),
338 Decoded::PartialChunk(_) => {}
339 new => unreachable!("{:?}", new),
340 }
341 }
342
343 Err(DecodingError::Format(
344 FormatErrorInner::UnexpectedEof.into(),
345 ))
346 }
347
348 fn info(&self) -> Option<&Info<'static>> {
349 self.decoder.info.as_ref()
350 }
351}
352
353/// PNG reader (mostly high-level interface)
354///
355/// Provides a high level that iterates over lines or whole images.
356pub struct Reader<R: Read> {
357 decoder: ReadDecoder<R>,
358 bpp: BytesPerPixel,
359 subframe: SubframeInfo,
360 /// Number of frame control chunks read.
361 /// By the APNG specification the total number must equal the count specified in the animation
362 /// control chunk. The IDAT image _may_ have such a chunk applying to it.
363 fctl_read: u32,
364 next_frame: SubframeIdx,
365 /// Vec containing the uncompressed image data currently being processed.
366 data_stream: Vec<u8>,
367 /// Index in `data_stream` where the previous row starts.
368 prev_start: usize,
369 /// Index in `data_stream` where the current row starts.
370 current_start: usize,
371 /// Output transformations
372 transform: Transformations,
373 /// Function that can transform decompressed, unfiltered rows into final output.
374 /// See the `transform.rs` module for more details.
375 transform_fn: Option<TransformFn>,
376 /// This buffer is only used so that `next_row` and `next_interlaced_row` can return reference
377 /// to a byte slice. In a future version of this library, this buffer will be removed and
378 /// `next_row` and `next_interlaced_row` will write directly into a user provided output buffer.
379 scratch_buffer: Vec<u8>,
380}
381
382/// The subframe specific information.
383///
384/// In APNG the frames are constructed by combining previous frame and a new subframe (through a
385/// combination of `dispose_op` and `overlay_op`). These sub frames specify individual dimension
386/// information and reuse the global interlace options. This struct encapsulates the state of where
387/// in a particular IDAT-frame or subframe we are.
388struct SubframeInfo {
389 width: u32,
390 height: u32,
391 rowlen: usize,
392 interlace: InterlaceIter,
393 consumed_and_flushed: bool,
394}
395
396#[derive(Clone)]
397enum InterlaceIter {
398 None(Range<u32>),
399 Adam7(adam7::Adam7Iterator),
400}
401
402/// Denote a frame as given by sequence numbers.
403#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
404enum SubframeIdx {
405 /// The initial frame in an IDAT chunk without fcTL chunk applying to it.
406 /// Note that this variant precedes `Some` as IDAT frames precede fdAT frames and all fdAT
407 /// frames must have a fcTL applying to it.
408 Initial,
409 /// An IDAT frame with fcTL or an fdAT frame.
410 Some(u32),
411 /// The past-the-end index.
412 End,
413}
414
415impl<R: Read> Reader<R> {
416 /// Reads all meta data until the next frame data starts.
417 /// Requires IHDR before the IDAT and fcTL before fdAT.
418 fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
419 loop {
420 // This is somewhat ugly. The API requires us to pass a buffer to decode_next but we
421 // know that we will stop before reading any image data from the stream. Thus pass an
422 // empty buffer and assert that remains empty.
423 let mut buf = Vec::new();
424 let state = self.decoder.decode_next(&mut buf)?;
425 assert!(buf.is_empty());
426
427 match state {
428 Some(Decoded::ChunkBegin(_, chunk::IDAT))
429 | Some(Decoded::ChunkBegin(_, chunk::fdAT)) => break,
430 Some(Decoded::FrameControl(_)) => {
431 self.subframe = SubframeInfo::new(self.info());
432 // The next frame is the one to which this chunk applies.
433 self.next_frame = SubframeIdx::Some(self.fctl_read);
434 // TODO: what about overflow here? That would imply there are more fctl chunks
435 // than can be specified in the animation control but also that we have read
436 // several gigabytes of data.
437 self.fctl_read += 1;
438 }
439 None => {
440 return Err(DecodingError::Format(
441 FormatErrorInner::MissingImageData.into(),
442 ))
443 }
444 // Ignore all other chunk events. Any other chunk may be between IDAT chunks, fdAT
445 // chunks and their control chunks.
446 _ => {}
447 }
448 }
449
450 let info = self
451 .decoder
452 .info()
453 .ok_or(DecodingError::Format(FormatErrorInner::MissingIhdr.into()))?;
454 self.bpp = info.bpp_in_prediction();
455 self.subframe = SubframeInfo::new(info);
456
457 // Allocate output buffer.
458 let buflen = self.output_line_size(self.subframe.width);
459 self.decoder.decoder.limits.reserve_bytes(buflen)?;
460
461 self.prev_start = self.current_start;
462
463 Ok(())
464 }
465
466 /// Get information on the image.
467 ///
468 /// The structure will change as new frames of an animated image are decoded.
469 pub fn info(&self) -> &Info<'static> {
470 self.decoder.info().unwrap()
471 }
472
473 /// Decodes the next frame into `buf`.
474 ///
475 /// Note that this decodes raw subframes that need to be mixed according to blend-op and
476 /// dispose-op by the caller.
477 ///
478 /// The caller must always provide a buffer large enough to hold a complete frame (the APNG
479 /// specification restricts subframes to the dimensions given in the image header). The region
480 /// that has been written be checked afterwards by calling `info` after a successful call and
481 /// inspecting the `frame_control` data. This requirement may be lifted in a later version of
482 /// `png`.
483 ///
484 /// Output lines will be written in row-major, packed matrix with width and height of the read
485 /// frame (or subframe), all samples are in big endian byte order where this matters.
486 pub fn next_frame(&mut self, buf: &mut [u8]) -> Result<OutputInfo, DecodingError> {
487 let subframe_idx = match self.decoder.info().unwrap().frame_control() {
488 None => SubframeIdx::Initial,
489 Some(_) => SubframeIdx::Some(self.fctl_read - 1),
490 };
491
492 if self.next_frame == SubframeIdx::End {
493 return Err(DecodingError::Parameter(
494 ParameterErrorKind::PolledAfterEndOfImage.into(),
495 ));
496 } else if self.next_frame != subframe_idx {
497 // Advance until we've read the info / fcTL for this frame.
498 self.read_until_image_data()?;
499 }
500
501 if buf.len() < self.output_buffer_size() {
502 return Err(DecodingError::Parameter(
503 ParameterErrorKind::ImageBufferSize {
504 expected: buf.len(),
505 actual: self.output_buffer_size(),
506 }
507 .into(),
508 ));
509 }
510
511 let (color_type, bit_depth) = self.output_color_type();
512 let output_info = OutputInfo {
513 width: self.subframe.width,
514 height: self.subframe.height,
515 color_type,
516 bit_depth,
517 line_size: self.output_line_size(self.subframe.width),
518 };
519
520 self.data_stream.clear();
521 self.current_start = 0;
522 self.prev_start = 0;
523 let width = self.info().width;
524 if self.info().interlaced {
525 while let Some(InterlacedRow {
526 data: row,
527 interlace,
528 ..
529 }) = self.next_interlaced_row()?
530 {
531 let (line, pass) = match interlace {
532 InterlaceInfo::Adam7 { line, pass, .. } => (line, pass),
533 InterlaceInfo::Null => unreachable!("expected interlace information"),
534 };
535 let samples = color_type.samples() as u8;
536 adam7::expand_pass(buf, width, row, pass, line, samples * (bit_depth as u8));
537 }
538 } else {
539 for row in buf
540 .chunks_exact_mut(output_info.line_size)
541 .take(self.subframe.height as usize)
542 {
543 self.next_interlaced_row_impl(self.subframe.rowlen, row)?;
544 }
545 }
546
547 // Advance over the rest of data for this (sub-)frame.
548 if !self.subframe.consumed_and_flushed {
549 self.decoder.finish_decoding()?;
550 }
551
552 // Advance our state to expect the next frame.
553 let past_end_subframe = self
554 .info()
555 .animation_control()
556 .map(|ac| ac.num_frames)
557 .unwrap_or(0);
558 self.next_frame = match self.next_frame {
559 SubframeIdx::End => unreachable!("Next frame called when already at image end"),
560 // Reached the end of non-animated image.
561 SubframeIdx::Initial if past_end_subframe == 0 => SubframeIdx::End,
562 // An animated image, expecting first subframe.
563 SubframeIdx::Initial => SubframeIdx::Some(0),
564 // This was the last subframe, slightly fuzzy condition in case of programmer error.
565 SubframeIdx::Some(idx) if past_end_subframe <= idx + 1 => SubframeIdx::End,
566 // Expecting next subframe.
567 SubframeIdx::Some(idx) => SubframeIdx::Some(idx + 1),
568 };
569
570 Ok(output_info)
571 }
572
573 /// Returns the next processed row of the image
574 pub fn next_row(&mut self) -> Result<Option<Row>, DecodingError> {
575 self.next_interlaced_row()
576 .map(|v| v.map(|v| Row { data: v.data }))
577 }
578
579 /// Returns the next processed row of the image
580 pub fn next_interlaced_row(&mut self) -> Result<Option<InterlacedRow>, DecodingError> {
581 let (rowlen, interlace) = match self.next_pass() {
582 Some((rowlen, interlace)) => (rowlen, interlace),
583 None => return Ok(None),
584 };
585
586 let width = if let InterlaceInfo::Adam7 { width, .. } = interlace {
587 width
588 } else {
589 self.subframe.width
590 };
591 let output_line_size = self.output_line_size(width);
592
593 // TODO: change the interface of `next_interlaced_row` to take an output buffer instead of
594 // making us return a reference to a buffer that we own.
595 let mut output_buffer = mem::take(&mut self.scratch_buffer);
596 output_buffer.resize(output_line_size, 0u8);
597 let ret = self.next_interlaced_row_impl(rowlen, &mut output_buffer);
598 self.scratch_buffer = output_buffer;
599 ret?;
600
601 Ok(Some(InterlacedRow {
602 data: &self.scratch_buffer[..output_line_size],
603 interlace,
604 }))
605 }
606
607 /// Read the rest of the image and chunks and finish up, including text chunks or others
608 /// 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`]
609 pub fn finish(&mut self) -> Result<(), DecodingError> {
610 self.next_frame = SubframeIdx::End;
611 self.data_stream.clear();
612 self.current_start = 0;
613 self.prev_start = 0;
614 loop {
615 let mut buf = Vec::new();
616 let state = self.decoder.decode_next(&mut buf)?;
617
618 if state.is_none() {
619 break;
620 }
621 }
622
623 Ok(())
624 }
625
626 /// Fetch the next interlaced row and filter it according to our own transformations.
627 fn next_interlaced_row_impl(
628 &mut self,
629 rowlen: usize,
630 output_buffer: &mut [u8],
631 ) -> Result<(), DecodingError> {
632 self.next_raw_interlaced_row(rowlen)?;
633 assert_eq!(self.current_start - self.prev_start, rowlen - 1);
634 let row = &self.data_stream[self.prev_start..self.current_start];
635
636 // Apply transformations and write resulting data to buffer.
637 let transform_fn = {
638 if self.transform_fn.is_none() {
639 self.transform_fn = Some(create_transform_fn(self.info(), self.transform)?);
640 }
641 self.transform_fn.as_deref().unwrap()
642 };
643 transform_fn(row, output_buffer, self.info());
644
645 Ok(())
646 }
647
648 /// Returns the color type and the number of bits per sample
649 /// of the data returned by `Reader::next_row` and Reader::frames`.
650 pub fn output_color_type(&self) -> (ColorType, BitDepth) {
651 use crate::common::ColorType::*;
652 let t = self.transform;
653 let info = self.info();
654 if t == Transformations::IDENTITY {
655 (info.color_type, info.bit_depth)
656 } else {
657 let bits = match info.bit_depth as u8 {
658 16 if t.intersects(Transformations::STRIP_16) => 8,
659 n if n < 8
660 && (t.contains(Transformations::EXPAND)
661 || t.contains(Transformations::ALPHA)) =>
662 {
663 8
664 }
665 n => n,
666 };
667 let color_type =
668 if t.contains(Transformations::EXPAND) || t.contains(Transformations::ALPHA) {
669 let has_trns = info.trns.is_some() || t.contains(Transformations::ALPHA);
670 match info.color_type {
671 Grayscale if has_trns => GrayscaleAlpha,
672 Rgb if has_trns => Rgba,
673 Indexed if has_trns => Rgba,
674 Indexed => Rgb,
675 ct => ct,
676 }
677 } else {
678 info.color_type
679 };
680 (color_type, BitDepth::from_u8(bits).unwrap())
681 }
682 }
683
684 /// Returns the number of bytes required to hold a deinterlaced image frame
685 /// that is decoded using the given input transformations.
686 pub fn output_buffer_size(&self) -> usize {
687 let (width, height) = self.info().size();
688 let size = self.output_line_size(width);
689 size * height as usize
690 }
691
692 /// Returns the number of bytes required to hold a deinterlaced row.
693 pub fn output_line_size(&self, width: u32) -> usize {
694 let (color, depth) = self.output_color_type();
695 color.raw_row_length_from_width(depth, width) - 1
696 }
697
698 fn next_pass(&mut self) -> Option<(usize, InterlaceInfo)> {
699 match self.subframe.interlace {
700 InterlaceIter::Adam7(ref mut adam7) => {
701 let last_pass = adam7.current_pass();
702 let (pass, line, width) = adam7.next()?;
703 let rowlen = self.info().raw_row_length_from_width(width);
704 if last_pass != pass {
705 self.prev_start = self.current_start;
706 }
707 Some((rowlen, InterlaceInfo::Adam7 { pass, line, width }))
708 }
709 InterlaceIter::None(ref mut height) => {
710 let _ = height.next()?;
711 Some((self.subframe.rowlen, InterlaceInfo::Null))
712 }
713 }
714 }
715
716 /// Write the next raw interlaced row into `self.prev`.
717 ///
718 /// The scanline is filtered against the previous scanline according to the specification.
719 fn next_raw_interlaced_row(&mut self, rowlen: usize) -> Result<(), DecodingError> {
720 // Read image data until we have at least one full row (but possibly more than one).
721 while self.data_stream.len() - self.current_start < rowlen {
722 if self.subframe.consumed_and_flushed {
723 return Err(DecodingError::Format(
724 FormatErrorInner::NoMoreImageData.into(),
725 ));
726 }
727
728 // Clear the current buffer before appending more data.
729 if self.prev_start > 0 {
730 self.data_stream.copy_within(self.prev_start.., 0);
731 self.data_stream
732 .truncate(self.data_stream.len() - self.prev_start);
733 self.current_start -= self.prev_start;
734 self.prev_start = 0;
735 }
736
737 match self.decoder.decode_next(&mut self.data_stream)? {
738 Some(Decoded::ImageData) => {}
739 Some(Decoded::ImageDataFlushed) => {
740 self.subframe.consumed_and_flushed = true;
741 }
742 None => {
743 return Err(DecodingError::Format(
744 if self.data_stream.is_empty() {
745 FormatErrorInner::NoMoreImageData
746 } else {
747 FormatErrorInner::UnexpectedEndOfChunk
748 }
749 .into(),
750 ));
751 }
752 _ => (),
753 }
754 }
755
756 // Get a reference to the current row and point scan_start to the next one.
757 let (prev, row) = self.data_stream.split_at_mut(self.current_start);
758
759 // Unfilter the row.
760 let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format(
761 FormatErrorInner::UnknownFilterMethod(row[0]).into(),
762 ))?;
763 unfilter(
764 filter,
765 self.bpp,
766 &prev[self.prev_start..],
767 &mut row[1..rowlen],
768 );
769
770 self.prev_start = self.current_start + 1;
771 self.current_start += rowlen;
772
773 Ok(())
774 }
775}
776
777impl SubframeInfo {
778 fn not_yet_init() -> Self {
779 SubframeInfo {
780 width: 0,
781 height: 0,
782 rowlen: 0,
783 interlace: InterlaceIter::None(0..0),
784 consumed_and_flushed: false,
785 }
786 }
787
788 fn new(info: &Info) -> Self {
789 // The apng fctnl overrides width and height.
790 // All other data is set by the main info struct.
791 let (width, height) = if let Some(fc) = info.frame_control {
792 (fc.width, fc.height)
793 } else {
794 (info.width, info.height)
795 };
796
797 let interlace = if info.interlaced {
798 InterlaceIter::Adam7(adam7::Adam7Iterator::new(width, height))
799 } else {
800 InterlaceIter::None(0..height)
801 };
802
803 SubframeInfo {
804 width,
805 height,
806 rowlen: info.raw_row_length_from_width(width),
807 interlace,
808 consumed_and_flushed: false,
809 }
810 }
811}
812