1use std::convert::TryInto;
2use std::error;
3use std::fmt;
4use std::io;
5use std::{borrow::Cow, cmp::min};
6
7use crc32fast::Hasher as Crc32;
8
9use super::zlib::ZlibStream;
10use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR};
11use crate::common::{
12 AnimationControl, BitDepth, BlendOp, ColorType, ContentLightLevelInfo, DisposeOp, FrameControl,
13 Info, MasteringDisplayColorVolume, ParameterError, ParameterErrorKind, PixelDimensions,
14 ScaledFloat, SourceChromaticities, Unit,
15};
16use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
17use crate::traits::ReadBytesExt;
18use crate::{CodingIndependentCodePoints, Limits};
19
20pub const CHUNK_BUFFER_SIZE: usize = 32 * 1024;
22
23const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
28
29#[derive(Debug)]
31enum U32ValueKind {
32 Signature1stU32,
35 Signature2ndU32,
38 Length,
41 Type { length: u32 },
44 Crc(ChunkType),
47 ApngSequenceNumber,
50}
51
52#[derive(Debug)]
53enum State {
54 U32 {
58 kind: U32ValueKind,
59 bytes: [u8; 4],
60 accumulated_count: usize,
61 },
62 ReadChunkData(ChunkType),
65 ParseChunkData(ChunkType),
68 ImageData(ChunkType),
71}
72
73impl State {
74 fn new_u32(kind: U32ValueKind) -> Self {
75 Self::U32 {
76 kind,
77 bytes: [0; 4],
78 accumulated_count: 0,
79 }
80 }
81}
82
83#[derive(Debug)]
84pub enum Decoded {
86 Nothing,
88 Header(u32, u32, BitDepth, ColorType, bool),
89 ChunkBegin(u32, ChunkType),
90 ChunkComplete(u32, ChunkType),
91 PixelDimensions(PixelDimensions),
92 AnimationControl(AnimationControl),
93 FrameControl(FrameControl),
94 ImageData,
96 ImageDataFlushed,
100 PartialChunk(ChunkType),
101 ImageEnd,
102}
103
104#[derive(Debug)]
110pub enum DecodingError {
111 IoError(io::Error),
118 Format(FormatError),
125 Parameter(ParameterError),
141 LimitsExceeded,
149}
150
151#[derive(Debug)]
152pub struct FormatError {
153 inner: FormatErrorInner,
154}
155
156#[derive(Debug)]
157pub(crate) enum FormatErrorInner {
158 CrcMismatch {
160 crc_val: u32,
162 crc_sum: u32,
164 chunk: ChunkType,
166 },
167 InvalidSignature,
169 MissingFctl,
172 MissingImageData,
174 ChunkBeforeIhdr {
176 kind: ChunkType,
177 },
178 AfterIdat {
180 kind: ChunkType,
181 },
182 BeforePlte {
184 kind: ChunkType,
185 },
186 AfterPlte {
188 kind: ChunkType,
189 },
190 OutsidePlteIdat {
192 kind: ChunkType,
193 },
194 DuplicateChunk {
196 kind: ChunkType,
197 },
198 ApngOrder {
200 present: u32,
202 expected: u32,
204 },
205 ShortPalette {
208 expected: usize,
209 len: usize,
210 },
211 InvalidSbitChunkSize {
213 color_type: ColorType,
214 expected: usize,
215 len: usize,
216 },
217 InvalidSbit {
218 sample_depth: BitDepth,
219 sbit: u8,
220 },
221 PaletteRequired,
223 InvalidColorBitDepth {
225 color_type: ColorType,
226 bit_depth: BitDepth,
227 },
228 ColorWithBadTrns(ColorType),
229 InvalidDimensions,
231 InvalidBitDepth(u8),
232 InvalidColorType(u8),
233 InvalidDisposeOp(u8),
234 InvalidBlendOp(u8),
235 InvalidUnit(u8),
236 InvalidSrgbRenderingIntent(u8),
238 UnknownCompressionMethod(u8),
239 UnknownFilterMethod(u8),
240 UnknownInterlaceMethod(u8),
241 BadSubFrameBounds {},
244 CorruptFlateStream {
247 err: fdeflate::DecompressionError,
248 },
249 NoMoreImageData,
251 BadTextEncoding(TextDecodingError),
253 FdatShorterThanFourBytes,
255 UnexpectedRestartOfDataChunkSequence {
264 kind: ChunkType,
265 },
266 ChunkTooShort {
268 kind: ChunkType,
269 },
270}
271
272impl error::Error for DecodingError {
273 fn cause(&self) -> Option<&(dyn error::Error + 'static)> {
274 match self {
275 DecodingError::IoError(err) => Some(err),
276 _ => None,
277 }
278 }
279}
280
281impl fmt::Display for DecodingError {
282 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
283 use self::DecodingError::*;
284 match self {
285 IoError(err) => write!(fmt, "{}", err),
286 Parameter(desc) => write!(fmt, "{}", &desc),
287 Format(desc) => write!(fmt, "{}", desc),
288 LimitsExceeded => write!(fmt, "limits are exceeded"),
289 }
290 }
291}
292
293impl fmt::Display for FormatError {
294 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
295 use FormatErrorInner::*;
296 match &self.inner {
297 CrcMismatch {
298 crc_val,
299 crc_sum,
300 chunk,
301 ..
302 } => write!(
303 fmt,
304 "CRC error: expected 0x{:x} have 0x{:x} while decoding {:?} chunk.",
305 crc_val, crc_sum, chunk
306 ),
307 MissingFctl => write!(fmt, "fcTL chunk missing before fdAT chunk."),
308 MissingImageData => write!(fmt, "IDAT or fdAT chunk is missing."),
309 ChunkBeforeIhdr { kind } => write!(fmt, "{:?} chunk appeared before IHDR chunk", kind),
310 AfterIdat { kind } => write!(fmt, "Chunk {:?} is invalid after IDAT chunk.", kind),
311 BeforePlte { kind } => write!(fmt, "Chunk {:?} is invalid before PLTE chunk.", kind),
312 AfterPlte { kind } => write!(fmt, "Chunk {:?} is invalid after PLTE chunk.", kind),
313 OutsidePlteIdat { kind } => write!(
314 fmt,
315 "Chunk {:?} must appear between PLTE and IDAT chunks.",
316 kind
317 ),
318 DuplicateChunk { kind } => write!(fmt, "Chunk {:?} must appear at most once.", kind),
319 ApngOrder { present, expected } => write!(
320 fmt,
321 "Sequence is not in order, expected #{} got #{}.",
322 expected, present,
323 ),
324 ShortPalette { expected, len } => write!(
325 fmt,
326 "Not enough palette entries, expect {} got {}.",
327 expected, len
328 ),
329 InvalidSbitChunkSize {color_type, expected, len} => write!(
330 fmt,
331 "The size of the sBIT chunk should be {} byte(s), but {} byte(s) were provided for the {:?} color type.",
332 expected, len, color_type
333 ),
334 InvalidSbit {sample_depth, sbit} => write!(
335 fmt,
336 "Invalid sBIT value {}. It must be greater than zero and less than the sample depth {:?}.",
337 sbit, sample_depth
338 ),
339 PaletteRequired => write!(fmt, "Missing palette of indexed image."),
340 InvalidDimensions => write!(fmt, "Invalid image dimensions"),
341 InvalidColorBitDepth {
342 color_type,
343 bit_depth,
344 } => write!(
345 fmt,
346 "Invalid color/depth combination in header: {:?}/{:?}",
347 color_type, bit_depth,
348 ),
349 ColorWithBadTrns(color_type) => write!(
350 fmt,
351 "Transparency chunk found for color type {:?}.",
352 color_type
353 ),
354 InvalidBitDepth(nr) => write!(fmt, "Invalid bit depth {}.", nr),
355 InvalidColorType(nr) => write!(fmt, "Invalid color type {}.", nr),
356 InvalidDisposeOp(nr) => write!(fmt, "Invalid dispose op {}.", nr),
357 InvalidBlendOp(nr) => write!(fmt, "Invalid blend op {}.", nr),
358 InvalidUnit(nr) => write!(fmt, "Invalid physical pixel size unit {}.", nr),
359 InvalidSrgbRenderingIntent(nr) => write!(fmt, "Invalid sRGB rendering intent {}.", nr),
360 UnknownCompressionMethod(nr) => write!(fmt, "Unknown compression method {}.", nr),
361 UnknownFilterMethod(nr) => write!(fmt, "Unknown filter method {}.", nr),
362 UnknownInterlaceMethod(nr) => write!(fmt, "Unknown interlace method {}.", nr),
363 BadSubFrameBounds {} => write!(fmt, "Sub frame is out-of-bounds."),
364 InvalidSignature => write!(fmt, "Invalid PNG signature."),
365 NoMoreImageData => write!(
366 fmt,
367 "IDAT or fDAT chunk does not have enough data for image."
368 ),
369 CorruptFlateStream { err } => {
370 write!(fmt, "Corrupt deflate stream. ")?;
371 write!(fmt, "{:?}", err)
372 }
373 BadTextEncoding(tde) => {
375 match tde {
376 TextDecodingError::Unrepresentable => {
377 write!(fmt, "Unrepresentable data in tEXt chunk.")
378 }
379 TextDecodingError::InvalidKeywordSize => {
380 write!(fmt, "Keyword empty or longer than 79 bytes.")
381 }
382 TextDecodingError::MissingNullSeparator => {
383 write!(fmt, "No null separator in tEXt chunk.")
384 }
385 TextDecodingError::InflationError => {
386 write!(fmt, "Invalid compressed text data.")
387 }
388 TextDecodingError::OutOfDecompressionSpace => {
389 write!(fmt, "Out of decompression space. Try with a larger limit.")
390 }
391 TextDecodingError::InvalidCompressionMethod => {
392 write!(fmt, "Using an unrecognized byte as compression method.")
393 }
394 TextDecodingError::InvalidCompressionFlag => {
395 write!(fmt, "Using a flag that is not 0 or 255 as a compression flag for iTXt chunk.")
396 }
397 TextDecodingError::MissingCompressionFlag => {
398 write!(fmt, "No compression flag in the iTXt chunk.")
399 }
400 }
401 }
402 FdatShorterThanFourBytes => write!(fmt, "fdAT chunk shorter than 4 bytes"),
403 UnexpectedRestartOfDataChunkSequence { kind } => {
404 write!(fmt, "Unexpected restart of {:?} chunk sequence", kind)
405 }
406 ChunkTooShort { kind } => {
407 write!(fmt, "Chunk is too short: {:?}", kind)
408 }
409 }
410 }
411}
412
413impl From<io::Error> for DecodingError {
414 fn from(err: io::Error) -> DecodingError {
415 DecodingError::IoError(err)
416 }
417}
418
419impl From<FormatError> for DecodingError {
420 fn from(err: FormatError) -> DecodingError {
421 DecodingError::Format(err)
422 }
423}
424
425impl From<FormatErrorInner> for FormatError {
426 fn from(inner: FormatErrorInner) -> Self {
427 FormatError { inner }
428 }
429}
430
431impl From<DecodingError> for io::Error {
432 fn from(err: DecodingError) -> io::Error {
433 match err {
434 DecodingError::IoError(err) => err,
435 err => io::Error::new(io::ErrorKind::Other, err.to_string()),
436 }
437 }
438}
439
440impl From<TextDecodingError> for DecodingError {
441 fn from(tbe: TextDecodingError) -> Self {
442 DecodingError::Format(FormatError {
443 inner: FormatErrorInner::BadTextEncoding(tbe),
444 })
445 }
446}
447
448#[derive(Clone)]
450pub struct DecodeOptions {
451 ignore_adler32: bool,
452 ignore_crc: bool,
453 ignore_text_chunk: bool,
454 ignore_iccp_chunk: bool,
455 skip_ancillary_crc_failures: bool,
456}
457
458impl Default for DecodeOptions {
459 fn default() -> Self {
460 Self {
461 ignore_adler32: true,
462 ignore_crc: false,
463 ignore_text_chunk: false,
464 ignore_iccp_chunk: false,
465 skip_ancillary_crc_failures: true,
466 }
467 }
468}
469
470impl DecodeOptions {
471 pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) {
475 self.ignore_adler32 = ignore_adler32;
476 }
477
478 pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
482 self.ignore_crc = ignore_crc;
483 }
484
485 pub fn set_ignore_checksums(&mut self, ignore_checksums: bool) {
488 self.ignore_adler32 = ignore_checksums;
489 self.ignore_crc = ignore_checksums;
490 }
491
492 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
496 self.ignore_text_chunk = ignore_text_chunk;
497 }
498
499 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
503 self.ignore_iccp_chunk = ignore_iccp_chunk;
504 }
505
506 pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
510 self.skip_ancillary_crc_failures = skip_ancillary_crc_failures;
511 }
512}
513
514pub struct StreamingDecoder {
520 state: Option<State>,
521 current_chunk: ChunkState,
522 inflater: ZlibStream,
524 pub(crate) info: Option<Info<'static>>,
526 current_seq_no: Option<u32>,
528 have_idat: bool,
531 ready_for_idat_chunks: bool,
534 ready_for_fdat_chunks: bool,
538 have_iccp: bool,
540 decode_options: DecodeOptions,
541 pub(crate) limits: Limits,
542}
543
544struct ChunkState {
545 type_: ChunkType,
548
549 crc: Crc32,
551
552 remaining: u32,
554
555 raw_bytes: Vec<u8>,
557}
558
559impl StreamingDecoder {
560 pub fn new() -> StreamingDecoder {
564 StreamingDecoder::new_with_options(DecodeOptions::default())
565 }
566
567 pub fn new_with_options(decode_options: DecodeOptions) -> StreamingDecoder {
568 let mut inflater = ZlibStream::new();
569 inflater.set_ignore_adler32(decode_options.ignore_adler32);
570
571 StreamingDecoder {
572 state: Some(State::new_u32(U32ValueKind::Signature1stU32)),
573 current_chunk: ChunkState::default(),
574 inflater,
575 info: None,
576 current_seq_no: None,
577 have_idat: false,
578 have_iccp: false,
579 ready_for_idat_chunks: true,
580 ready_for_fdat_chunks: false,
581 decode_options,
582 limits: Limits { bytes: usize::MAX },
583 }
584 }
585
586 pub fn reset(&mut self) {
588 self.state = Some(State::new_u32(U32ValueKind::Signature1stU32));
589 self.current_chunk.crc = Crc32::new();
590 self.current_chunk.remaining = 0;
591 self.current_chunk.raw_bytes.clear();
592 self.inflater.reset();
593 self.info = None;
594 self.current_seq_no = None;
595 self.have_idat = false;
596 }
597
598 pub fn info(&self) -> Option<&Info<'static>> {
600 self.info.as_ref()
601 }
602
603 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
604 self.decode_options.set_ignore_text_chunk(ignore_text_chunk);
605 }
606
607 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
608 self.decode_options.set_ignore_iccp_chunk(ignore_iccp_chunk);
609 }
610
611 pub fn ignore_adler32(&self) -> bool {
613 self.inflater.ignore_adler32()
614 }
615
616 pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) -> bool {
624 self.inflater.set_ignore_adler32(ignore_adler32)
625 }
626
627 pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
632 self.decode_options.set_ignore_crc(ignore_crc)
633 }
634
635 pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
639 self.decode_options
640 .set_skip_ancillary_crc_failures(skip_ancillary_crc_failures)
641 }
642
643 pub fn update(
649 &mut self,
650 mut buf: &[u8],
651 image_data: &mut Vec<u8>,
652 ) -> Result<(usize, Decoded), DecodingError> {
653 if self.state.is_none() {
654 return Err(DecodingError::Parameter(
655 ParameterErrorKind::PolledAfterFatalError.into(),
656 ));
657 }
658
659 let len = buf.len();
660 while !buf.is_empty() {
661 match self.next_state(buf, image_data) {
662 Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..],
663 Ok((bytes, result)) => {
664 buf = &buf[bytes..];
665 return Ok((len - buf.len(), result));
666 }
667 Err(err) => {
668 debug_assert!(self.state.is_none());
669 return Err(err);
670 }
671 }
672 }
673 Ok((len - buf.len(), Decoded::Nothing))
674 }
675
676 fn next_state(
677 &mut self,
678 buf: &[u8],
679 image_data: &mut Vec<u8>,
680 ) -> Result<(usize, Decoded), DecodingError> {
681 use self::State::*;
682
683 let state = self.state.take().unwrap();
685
686 match state {
687 U32 {
688 kind,
689 mut bytes,
690 mut accumulated_count,
691 } => {
692 debug_assert!(accumulated_count <= 4);
693 if accumulated_count == 0 && buf.len() >= 4 {
694 const CONSUMED_BYTES: usize = 4;
700 self.parse_u32(kind, &buf[0..4], image_data)
701 .map(|decoded| (CONSUMED_BYTES, decoded))
702 } else {
703 let remaining_count = 4 - accumulated_count;
704 let consumed_bytes = {
705 let available_count = min(remaining_count, buf.len());
706 bytes[accumulated_count..accumulated_count + available_count]
707 .copy_from_slice(&buf[0..available_count]);
708 accumulated_count += available_count;
709 available_count
710 };
711
712 if accumulated_count < 4 {
713 self.state = Some(U32 {
714 kind,
715 bytes,
716 accumulated_count,
717 });
718 Ok((consumed_bytes, Decoded::Nothing))
719 } else {
720 debug_assert_eq!(accumulated_count, 4);
721 self.parse_u32(kind, &bytes, image_data)
722 .map(|decoded| (consumed_bytes, decoded))
723 }
724 }
725 }
726 ParseChunkData(type_str) => {
727 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
728 if self.current_chunk.remaining == 0 {
729 Ok((0, self.parse_chunk(type_str)?))
731 } else {
732 self.reserve_current_chunk()?;
735
736 self.state = Some(ReadChunkData(type_str));
737 Ok((0, Decoded::PartialChunk(type_str)))
738 }
739 }
740 ReadChunkData(type_str) => {
741 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
742 if self.current_chunk.remaining == 0 {
743 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
744 Ok((0, Decoded::Nothing))
745 } else {
746 let ChunkState {
747 crc,
748 remaining,
749 raw_bytes,
750 type_: _,
751 } = &mut self.current_chunk;
752
753 let buf_avail = raw_bytes.capacity() - raw_bytes.len();
754 let bytes_avail = min(buf.len(), buf_avail);
755 let n = min(*remaining, bytes_avail as u32);
756 if buf_avail == 0 {
757 self.state = Some(ParseChunkData(type_str));
758 Ok((0, Decoded::Nothing))
759 } else {
760 let buf = &buf[..n as usize];
761 if !self.decode_options.ignore_crc {
762 crc.update(buf);
763 }
764 raw_bytes.extend_from_slice(buf);
765
766 *remaining -= n;
767 if *remaining == 0 {
768 self.state = Some(ParseChunkData(type_str));
769 } else {
770 self.state = Some(ReadChunkData(type_str));
771 }
772 Ok((n as usize, Decoded::Nothing))
773 }
774 }
775 }
776 ImageData(type_str) => {
777 debug_assert!(type_str == IDAT || type_str == chunk::fdAT);
778 let len = std::cmp::min(buf.len(), self.current_chunk.remaining as usize);
779 let buf = &buf[..len];
780 let consumed = self.inflater.decompress(buf, image_data)?;
781 self.current_chunk.crc.update(&buf[..consumed]);
782 self.current_chunk.remaining -= consumed as u32;
783 if self.current_chunk.remaining == 0 {
784 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
785 } else {
786 self.state = Some(ImageData(type_str));
787 }
788 Ok((consumed, Decoded::ImageData))
789 }
790 }
791 }
792
793 fn parse_u32(
794 &mut self,
795 kind: U32ValueKind,
796 u32_be_bytes: &[u8],
797 image_data: &mut Vec<u8>,
798 ) -> Result<Decoded, DecodingError> {
799 debug_assert_eq!(u32_be_bytes.len(), 4);
800 let bytes = u32_be_bytes.try_into().unwrap();
801 let val = u32::from_be_bytes(bytes);
802
803 match kind {
804 U32ValueKind::Signature1stU32 => {
805 if bytes == [137, 80, 78, 71] {
806 self.state = Some(State::new_u32(U32ValueKind::Signature2ndU32));
807 Ok(Decoded::Nothing)
808 } else {
809 Err(DecodingError::Format(
810 FormatErrorInner::InvalidSignature.into(),
811 ))
812 }
813 }
814 U32ValueKind::Signature2ndU32 => {
815 if bytes == [13, 10, 26, 10] {
816 self.state = Some(State::new_u32(U32ValueKind::Length));
817 Ok(Decoded::Nothing)
818 } else {
819 Err(DecodingError::Format(
820 FormatErrorInner::InvalidSignature.into(),
821 ))
822 }
823 }
824 U32ValueKind::Length => {
825 self.state = Some(State::new_u32(U32ValueKind::Type { length: val }));
826 Ok(Decoded::Nothing)
827 }
828 U32ValueKind::Type { length } => {
829 let type_str = ChunkType(bytes);
830 if self.info.is_none() && type_str != IHDR {
831 return Err(DecodingError::Format(
832 FormatErrorInner::ChunkBeforeIhdr { kind: type_str }.into(),
833 ));
834 }
835 if type_str != self.current_chunk.type_
836 && (self.current_chunk.type_ == IDAT || self.current_chunk.type_ == chunk::fdAT)
837 {
838 self.current_chunk.type_ = type_str;
839 self.inflater.finish_compressed_chunks(image_data)?;
840 self.inflater.reset();
841 self.ready_for_idat_chunks = false;
842 self.ready_for_fdat_chunks = false;
843 self.state = Some(State::U32 {
844 kind,
845 bytes,
846 accumulated_count: 4,
847 });
848 return Ok(Decoded::ImageDataFlushed);
849 }
850 self.state = match type_str {
851 chunk::fdAT => {
852 if !self.ready_for_fdat_chunks {
853 return Err(DecodingError::Format(
854 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
855 kind: chunk::fdAT,
856 }
857 .into(),
858 ));
859 }
860 if length < 4 {
861 return Err(DecodingError::Format(
862 FormatErrorInner::FdatShorterThanFourBytes.into(),
863 ));
864 }
865 Some(State::new_u32(U32ValueKind::ApngSequenceNumber))
866 }
867 IDAT => {
868 if !self.ready_for_idat_chunks {
869 return Err(DecodingError::Format(
870 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
871 kind: IDAT,
872 }
873 .into(),
874 ));
875 }
876 self.have_idat = true;
877 Some(State::ImageData(type_str))
878 }
879 _ => Some(State::ReadChunkData(type_str)),
880 };
881 self.current_chunk.type_ = type_str;
882 if !self.decode_options.ignore_crc {
883 self.current_chunk.crc.reset();
884 self.current_chunk.crc.update(&type_str.0);
885 }
886 self.current_chunk.remaining = length;
887 self.current_chunk.raw_bytes.clear();
888 Ok(Decoded::ChunkBegin(length, type_str))
889 }
890 U32ValueKind::Crc(type_str) => {
891 let sum = if self.decode_options.ignore_crc {
895 val
896 } else {
897 self.current_chunk.crc.clone().finalize()
898 };
899
900 if val == sum || CHECKSUM_DISABLED {
901 if type_str == IEND {
902 debug_assert!(self.state.is_none());
903 Ok(Decoded::ImageEnd)
904 } else {
905 self.state = Some(State::new_u32(U32ValueKind::Length));
906 Ok(Decoded::ChunkComplete(val, type_str))
907 }
908 } else if self.decode_options.skip_ancillary_crc_failures
909 && !chunk::is_critical(type_str)
910 {
911 self.state = Some(State::new_u32(U32ValueKind::Length));
913 Ok(Decoded::Nothing)
914 } else {
915 Err(DecodingError::Format(
916 FormatErrorInner::CrcMismatch {
917 crc_val: val,
918 crc_sum: sum,
919 chunk: type_str,
920 }
921 .into(),
922 ))
923 }
924 }
925 U32ValueKind::ApngSequenceNumber => {
926 debug_assert_eq!(self.current_chunk.type_, chunk::fdAT);
927 let next_seq_no = val;
928
929 debug_assert!(self.current_chunk.remaining >= 4);
931 self.current_chunk.remaining -= 4;
932
933 if let Some(seq_no) = self.current_seq_no {
934 if next_seq_no != seq_no + 1 {
935 return Err(DecodingError::Format(
936 FormatErrorInner::ApngOrder {
937 present: next_seq_no,
938 expected: seq_no + 1,
939 }
940 .into(),
941 ));
942 }
943 self.current_seq_no = Some(next_seq_no);
944 } else {
945 return Err(DecodingError::Format(FormatErrorInner::MissingFctl.into()));
946 }
947
948 if !self.decode_options.ignore_crc {
949 let data = next_seq_no.to_be_bytes();
950 self.current_chunk.crc.update(&data);
951 }
952
953 self.state = Some(State::ImageData(chunk::fdAT));
954 Ok(Decoded::PartialChunk(chunk::fdAT))
955 }
956 }
957 }
958
959 fn reserve_current_chunk(&mut self) -> Result<(), DecodingError> {
960 let max = self.limits.bytes;
961 let buffer = &mut self.current_chunk.raw_bytes;
962
963 let reserve_size = max.saturating_sub(buffer.capacity()).min(buffer.len());
965 self.limits.reserve_bytes(reserve_size)?;
966 buffer.reserve_exact(reserve_size);
967
968 if buffer.capacity() == buffer.len() {
969 Err(DecodingError::LimitsExceeded)
970 } else {
971 Ok(())
972 }
973 }
974
975 fn parse_chunk(&mut self, type_str: ChunkType) -> Result<Decoded, DecodingError> {
976 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
977 let parse_result = match type_str {
978 IHDR => self.parse_ihdr(),
979 chunk::sBIT => self.parse_sbit(),
980 chunk::PLTE => self.parse_plte(),
981 chunk::tRNS => self.parse_trns(),
982 chunk::pHYs => self.parse_phys(),
983 chunk::gAMA => self.parse_gama(),
984 chunk::acTL => self.parse_actl(),
985 chunk::fcTL => self.parse_fctl(),
986 chunk::cHRM => self.parse_chrm(),
987 chunk::sRGB => self.parse_srgb(),
988 chunk::cICP => Ok(self.parse_cicp()),
989 chunk::mDCV => Ok(self.parse_mdcv()),
990 chunk::cLLI => Ok(self.parse_clli()),
991 chunk::bKGD => Ok(self.parse_bkgd()),
992 chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
993 chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
994 chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(),
995 chunk::iTXt if !self.decode_options.ignore_text_chunk => self.parse_itxt(),
996 _ => Ok(Decoded::PartialChunk(type_str)),
997 };
998
999 parse_result.map_err(|e| {
1000 self.state = None;
1001 match e {
1002 DecodingError::IoError(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
1007 let fmt_err: FormatError =
1008 FormatErrorInner::ChunkTooShort { kind: type_str }.into();
1009 fmt_err.into()
1010 }
1011 e => e,
1012 }
1013 })
1014 }
1015
1016 fn parse_fctl(&mut self) -> Result<Decoded, DecodingError> {
1017 let mut buf = &self.current_chunk.raw_bytes[..];
1018 let next_seq_no = buf.read_be()?;
1019
1020 self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
1022 if next_seq_no != seq_no + 1 {
1023 return Err(DecodingError::Format(
1024 FormatErrorInner::ApngOrder {
1025 expected: seq_no + 1,
1026 present: next_seq_no,
1027 }
1028 .into(),
1029 ));
1030 }
1031 next_seq_no
1032 } else {
1033 if next_seq_no != 0 {
1034 return Err(DecodingError::Format(
1035 FormatErrorInner::ApngOrder {
1036 expected: 0,
1037 present: next_seq_no,
1038 }
1039 .into(),
1040 ));
1041 }
1042 0
1043 });
1044 self.inflater.reset();
1045 self.ready_for_fdat_chunks = true;
1046 let fc = FrameControl {
1047 sequence_number: next_seq_no,
1048 width: buf.read_be()?,
1049 height: buf.read_be()?,
1050 x_offset: buf.read_be()?,
1051 y_offset: buf.read_be()?,
1052 delay_num: buf.read_be()?,
1053 delay_den: buf.read_be()?,
1054 dispose_op: {
1055 let dispose_op = buf.read_be()?;
1056 match DisposeOp::from_u8(dispose_op) {
1057 Some(dispose_op) => dispose_op,
1058 None => {
1059 return Err(DecodingError::Format(
1060 FormatErrorInner::InvalidDisposeOp(dispose_op).into(),
1061 ))
1062 }
1063 }
1064 },
1065 blend_op: {
1066 let blend_op = buf.read_be()?;
1067 match BlendOp::from_u8(blend_op) {
1068 Some(blend_op) => blend_op,
1069 None => {
1070 return Err(DecodingError::Format(
1071 FormatErrorInner::InvalidBlendOp(blend_op).into(),
1072 ))
1073 }
1074 }
1075 },
1076 };
1077 self.info.as_ref().unwrap().validate(&fc)?;
1078 self.info.as_mut().unwrap().frame_control = Some(fc);
1079 Ok(Decoded::FrameControl(fc))
1080 }
1081
1082 fn parse_actl(&mut self) -> Result<Decoded, DecodingError> {
1083 if self.have_idat {
1084 Err(DecodingError::Format(
1085 FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1086 ))
1087 } else {
1088 let mut buf = &self.current_chunk.raw_bytes[..];
1089 let actl = AnimationControl {
1090 num_frames: buf.read_be()?,
1091 num_plays: buf.read_be()?,
1092 };
1093 self.info.as_mut().unwrap().animation_control = Some(actl);
1094 Ok(Decoded::AnimationControl(actl))
1095 }
1096 }
1097
1098 fn parse_plte(&mut self) -> Result<Decoded, DecodingError> {
1099 let info = self.info.as_mut().unwrap();
1100 if info.palette.is_some() {
1101 Err(DecodingError::Format(
1103 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1104 ))
1105 } else {
1106 self.limits
1107 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1108 info.palette = Some(Cow::Owned(self.current_chunk.raw_bytes.clone()));
1109 Ok(Decoded::Nothing)
1110 }
1111 }
1112
1113 fn parse_sbit(&mut self) -> Result<Decoded, DecodingError> {
1114 let mut parse = || {
1115 let info = self.info.as_mut().unwrap();
1116 if info.palette.is_some() {
1117 return Err(DecodingError::Format(
1118 FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
1119 ));
1120 }
1121
1122 if self.have_idat {
1123 return Err(DecodingError::Format(
1124 FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
1125 ));
1126 }
1127
1128 if info.sbit.is_some() {
1129 return Err(DecodingError::Format(
1130 FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
1131 ));
1132 }
1133
1134 let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
1135 let sample_depth = if color_type == ColorType::Indexed {
1137 BitDepth::Eight
1138 } else {
1139 bit_depth
1140 };
1141 self.limits
1142 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1143 let vec = self.current_chunk.raw_bytes.clone();
1144 let len = vec.len();
1145
1146 let expected = match color_type {
1148 ColorType::Grayscale => 1,
1149 ColorType::Rgb | ColorType::Indexed => 3,
1150 ColorType::GrayscaleAlpha => 2,
1151 ColorType::Rgba => 4,
1152 };
1153
1154 if expected != len {
1156 return Err(DecodingError::Format(
1157 FormatErrorInner::InvalidSbitChunkSize {
1158 color_type,
1159 expected,
1160 len,
1161 }
1162 .into(),
1163 ));
1164 }
1165
1166 for sbit in &vec {
1167 if *sbit < 1 || *sbit > sample_depth as u8 {
1168 return Err(DecodingError::Format(
1169 FormatErrorInner::InvalidSbit {
1170 sample_depth,
1171 sbit: *sbit,
1172 }
1173 .into(),
1174 ));
1175 }
1176 }
1177 info.sbit = Some(Cow::Owned(vec));
1178 Ok(Decoded::Nothing)
1179 };
1180
1181 parse().ok();
1182 Ok(Decoded::Nothing)
1183 }
1184
1185 fn parse_trns(&mut self) -> Result<Decoded, DecodingError> {
1186 let info = self.info.as_mut().unwrap();
1187 if info.trns.is_some() {
1188 return Err(DecodingError::Format(
1189 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1190 ));
1191 }
1192 let (color_type, bit_depth) = { (info.color_type, info.bit_depth as u8) };
1193 self.limits
1194 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1195 let mut vec = self.current_chunk.raw_bytes.clone();
1196 let len = vec.len();
1197 match color_type {
1198 ColorType::Grayscale => {
1199 if len < 2 {
1200 return Err(DecodingError::Format(
1201 FormatErrorInner::ShortPalette { expected: 2, len }.into(),
1202 ));
1203 }
1204 if bit_depth < 16 {
1205 vec[0] = vec[1];
1206 vec.truncate(1);
1207 }
1208 info.trns = Some(Cow::Owned(vec));
1209 Ok(Decoded::Nothing)
1210 }
1211 ColorType::Rgb => {
1212 if len < 6 {
1213 return Err(DecodingError::Format(
1214 FormatErrorInner::ShortPalette { expected: 6, len }.into(),
1215 ));
1216 }
1217 if bit_depth < 16 {
1218 vec[0] = vec[1];
1219 vec[1] = vec[3];
1220 vec[2] = vec[5];
1221 vec.truncate(3);
1222 }
1223 info.trns = Some(Cow::Owned(vec));
1224 Ok(Decoded::Nothing)
1225 }
1226 ColorType::Indexed => {
1227 if info.palette.is_none() {
1230 return Err(DecodingError::Format(
1231 FormatErrorInner::BeforePlte { kind: chunk::tRNS }.into(),
1232 ));
1233 } else if self.have_idat {
1234 return Err(DecodingError::Format(
1235 FormatErrorInner::OutsidePlteIdat { kind: chunk::tRNS }.into(),
1236 ));
1237 }
1238
1239 info.trns = Some(Cow::Owned(vec));
1240 Ok(Decoded::Nothing)
1241 }
1242 c => Err(DecodingError::Format(
1243 FormatErrorInner::ColorWithBadTrns(c).into(),
1244 )),
1245 }
1246 }
1247
1248 fn parse_phys(&mut self) -> Result<Decoded, DecodingError> {
1249 let info = self.info.as_mut().unwrap();
1250 if self.have_idat {
1251 Err(DecodingError::Format(
1252 FormatErrorInner::AfterIdat { kind: chunk::pHYs }.into(),
1253 ))
1254 } else if info.pixel_dims.is_some() {
1255 Err(DecodingError::Format(
1256 FormatErrorInner::DuplicateChunk { kind: chunk::pHYs }.into(),
1257 ))
1258 } else {
1259 let mut buf = &self.current_chunk.raw_bytes[..];
1260 let xppu = buf.read_be()?;
1261 let yppu = buf.read_be()?;
1262 let unit = buf.read_be()?;
1263 let unit = match Unit::from_u8(unit) {
1264 Some(unit) => unit,
1265 None => {
1266 return Err(DecodingError::Format(
1267 FormatErrorInner::InvalidUnit(unit).into(),
1268 ))
1269 }
1270 };
1271 let pixel_dims = PixelDimensions { xppu, yppu, unit };
1272 info.pixel_dims = Some(pixel_dims);
1273 Ok(Decoded::PixelDimensions(pixel_dims))
1274 }
1275 }
1276
1277 fn parse_chrm(&mut self) -> Result<Decoded, DecodingError> {
1278 let info = self.info.as_mut().unwrap();
1279 if self.have_idat {
1280 Err(DecodingError::Format(
1281 FormatErrorInner::AfterIdat { kind: chunk::cHRM }.into(),
1282 ))
1283 } else if info.chrm_chunk.is_some() {
1284 Err(DecodingError::Format(
1285 FormatErrorInner::DuplicateChunk { kind: chunk::cHRM }.into(),
1286 ))
1287 } else {
1288 let mut buf = &self.current_chunk.raw_bytes[..];
1289 let white_x: u32 = buf.read_be()?;
1290 let white_y: u32 = buf.read_be()?;
1291 let red_x: u32 = buf.read_be()?;
1292 let red_y: u32 = buf.read_be()?;
1293 let green_x: u32 = buf.read_be()?;
1294 let green_y: u32 = buf.read_be()?;
1295 let blue_x: u32 = buf.read_be()?;
1296 let blue_y: u32 = buf.read_be()?;
1297
1298 let source_chromaticities = SourceChromaticities {
1299 white: (
1300 ScaledFloat::from_scaled(white_x),
1301 ScaledFloat::from_scaled(white_y),
1302 ),
1303 red: (
1304 ScaledFloat::from_scaled(red_x),
1305 ScaledFloat::from_scaled(red_y),
1306 ),
1307 green: (
1308 ScaledFloat::from_scaled(green_x),
1309 ScaledFloat::from_scaled(green_y),
1310 ),
1311 blue: (
1312 ScaledFloat::from_scaled(blue_x),
1313 ScaledFloat::from_scaled(blue_y),
1314 ),
1315 };
1316
1317 info.chrm_chunk = Some(source_chromaticities);
1318 if info.srgb.is_none() {
1320 info.source_chromaticities = Some(source_chromaticities);
1321 }
1322
1323 Ok(Decoded::Nothing)
1324 }
1325 }
1326
1327 fn parse_gama(&mut self) -> Result<Decoded, DecodingError> {
1328 let info = self.info.as_mut().unwrap();
1329 if self.have_idat {
1330 Err(DecodingError::Format(
1331 FormatErrorInner::AfterIdat { kind: chunk::gAMA }.into(),
1332 ))
1333 } else if info.gama_chunk.is_some() {
1334 Err(DecodingError::Format(
1335 FormatErrorInner::DuplicateChunk { kind: chunk::gAMA }.into(),
1336 ))
1337 } else {
1338 let mut buf = &self.current_chunk.raw_bytes[..];
1339 let source_gamma: u32 = buf.read_be()?;
1340 let source_gamma = ScaledFloat::from_scaled(source_gamma);
1341
1342 info.gama_chunk = Some(source_gamma);
1343 if info.srgb.is_none() {
1345 info.source_gamma = Some(source_gamma);
1346 }
1347
1348 Ok(Decoded::Nothing)
1349 }
1350 }
1351
1352 fn parse_srgb(&mut self) -> Result<Decoded, DecodingError> {
1353 let info = self.info.as_mut().unwrap();
1354 if self.have_idat {
1355 Err(DecodingError::Format(
1356 FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1357 ))
1358 } else if info.srgb.is_some() {
1359 Err(DecodingError::Format(
1360 FormatErrorInner::DuplicateChunk { kind: chunk::sRGB }.into(),
1361 ))
1362 } else {
1363 let mut buf = &self.current_chunk.raw_bytes[..];
1364 let raw: u8 = buf.read_be()?; let rendering_intent = crate::SrgbRenderingIntent::from_raw(raw).ok_or_else(|| {
1366 FormatError::from(FormatErrorInner::InvalidSrgbRenderingIntent(raw))
1367 })?;
1368
1369 info.srgb = Some(rendering_intent);
1371 info.source_gamma = Some(crate::srgb::substitute_gamma());
1372 info.source_chromaticities = Some(crate::srgb::substitute_chromaticities());
1373 Ok(Decoded::Nothing)
1374 }
1375 }
1376
1377 fn parse_cicp(&mut self) -> Decoded {
1381 fn parse(mut buf: &[u8]) -> Result<CodingIndependentCodePoints, std::io::Error> {
1382 let color_primaries: u8 = buf.read_be()?;
1383 let transfer_function: u8 = buf.read_be()?;
1384 let matrix_coefficients: u8 = buf.read_be()?;
1385 let is_video_full_range_image = {
1386 let flag: u8 = buf.read_be()?;
1387 match flag {
1388 0 => false,
1389 1 => true,
1390 _ => {
1391 return Err(std::io::ErrorKind::InvalidData.into());
1392 }
1393 }
1394 };
1395
1396 if matrix_coefficients != 0 {
1399 return Err(std::io::ErrorKind::InvalidData.into());
1400 }
1401
1402 if !buf.is_empty() {
1403 return Err(std::io::ErrorKind::InvalidData.into());
1404 }
1405
1406 Ok(CodingIndependentCodePoints {
1407 color_primaries,
1408 transfer_function,
1409 matrix_coefficients,
1410 is_video_full_range_image,
1411 })
1412 }
1413
1414 let info = self.info.as_mut().unwrap();
1417 let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
1418 if is_before_plte_and_idat && info.coding_independent_code_points.is_none() {
1419 info.coding_independent_code_points = parse(&self.current_chunk.raw_bytes[..]).ok();
1420 }
1421
1422 Decoded::Nothing
1423 }
1424
1425 fn parse_mdcv(&mut self) -> Decoded {
1429 fn parse(mut buf: &[u8]) -> Result<MasteringDisplayColorVolume, std::io::Error> {
1430 let red_x: u16 = buf.read_be()?;
1431 let red_y: u16 = buf.read_be()?;
1432 let green_x: u16 = buf.read_be()?;
1433 let green_y: u16 = buf.read_be()?;
1434 let blue_x: u16 = buf.read_be()?;
1435 let blue_y: u16 = buf.read_be()?;
1436 let white_x: u16 = buf.read_be()?;
1437 let white_y: u16 = buf.read_be()?;
1438 fn scale(chunk: u16) -> ScaledFloat {
1439 ScaledFloat::from_scaled((chunk as u32) * 2)
1446 }
1447 let chromaticities = SourceChromaticities {
1448 white: (scale(white_x), scale(white_y)),
1449 red: (scale(red_x), scale(red_y)),
1450 green: (scale(green_x), scale(green_y)),
1451 blue: (scale(blue_x), scale(blue_y)),
1452 };
1453 let max_luminance: u32 = buf.read_be()?;
1454 let min_luminance: u32 = buf.read_be()?;
1455 if !buf.is_empty() {
1456 return Err(std::io::ErrorKind::InvalidData.into());
1457 }
1458 Ok(MasteringDisplayColorVolume {
1459 chromaticities,
1460 max_luminance,
1461 min_luminance,
1462 })
1463 }
1464
1465 let info = self.info.as_mut().unwrap();
1468 let is_before_plte_and_idat = !self.have_idat && info.palette.is_none();
1469 if is_before_plte_and_idat && info.mastering_display_color_volume.is_none() {
1470 info.mastering_display_color_volume = parse(&self.current_chunk.raw_bytes[..]).ok();
1471 }
1472
1473 Decoded::Nothing
1474 }
1475
1476 fn parse_clli(&mut self) -> Decoded {
1480 fn parse(mut buf: &[u8]) -> Result<ContentLightLevelInfo, std::io::Error> {
1481 let max_content_light_level: u32 = buf.read_be()?;
1482 let max_frame_average_light_level: u32 = buf.read_be()?;
1483 if !buf.is_empty() {
1484 return Err(std::io::ErrorKind::InvalidData.into());
1485 }
1486 Ok(ContentLightLevelInfo {
1487 max_content_light_level,
1488 max_frame_average_light_level,
1489 })
1490 }
1491
1492 let info = self.info.as_mut().unwrap();
1494 if info.content_light_level.is_none() {
1495 info.content_light_level = parse(&self.current_chunk.raw_bytes[..]).ok();
1496 }
1497
1498 Decoded::Nothing
1499 }
1500
1501 fn parse_iccp(&mut self) -> Result<Decoded, DecodingError> {
1502 if self.have_idat {
1503 Err(DecodingError::Format(
1504 FormatErrorInner::AfterIdat { kind: chunk::iCCP }.into(),
1505 ))
1506 } else if self.have_iccp {
1507 Ok(Decoded::Nothing)
1519 } else {
1520 self.have_iccp = true;
1521 let _ = self.parse_iccp_raw();
1522 Ok(Decoded::Nothing)
1523 }
1524 }
1525
1526 fn parse_iccp_raw(&mut self) -> Result<(), DecodingError> {
1527 let info = self.info.as_mut().unwrap();
1528 let mut buf = &self.current_chunk.raw_bytes[..];
1529
1530 for len in 0..=80 {
1532 let raw: u8 = buf.read_be()?;
1533 if (raw == 0 && len == 0) || (raw != 0 && len == 80) {
1534 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1535 }
1536 if raw == 0 {
1537 break;
1538 }
1539 }
1540
1541 match buf.read_be()? {
1542 0u8 => (),
1544 n => {
1545 return Err(DecodingError::Format(
1546 FormatErrorInner::UnknownCompressionMethod(n).into(),
1547 ))
1548 }
1549 }
1550
1551 match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) {
1552 Ok(profile) => {
1553 self.limits.reserve_bytes(profile.len())?;
1554 info.icc_profile = Some(Cow::Owned(profile));
1555 }
1556 Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => {
1557 return Err(DecodingError::Format(
1558 FormatErrorInner::CorruptFlateStream { err }.into(),
1559 ))
1560 }
1561 Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => {
1562 return Err(DecodingError::LimitsExceeded);
1563 }
1564 }
1565
1566 Ok(())
1567 }
1568
1569 fn parse_ihdr(&mut self) -> Result<Decoded, DecodingError> {
1570 if self.info.is_some() {
1571 return Err(DecodingError::Format(
1572 FormatErrorInner::DuplicateChunk { kind: IHDR }.into(),
1573 ));
1574 }
1575 let mut buf = &self.current_chunk.raw_bytes[..];
1576 let width = buf.read_be()?;
1577 let height = buf.read_be()?;
1578 if width == 0 || height == 0 {
1579 return Err(DecodingError::Format(
1580 FormatErrorInner::InvalidDimensions.into(),
1581 ));
1582 }
1583 let bit_depth = buf.read_be()?;
1584 let bit_depth = match BitDepth::from_u8(bit_depth) {
1585 Some(bits) => bits,
1586 None => {
1587 return Err(DecodingError::Format(
1588 FormatErrorInner::InvalidBitDepth(bit_depth).into(),
1589 ))
1590 }
1591 };
1592 let color_type = buf.read_be()?;
1593 let color_type = match ColorType::from_u8(color_type) {
1594 Some(color_type) => {
1595 if color_type.is_combination_invalid(bit_depth) {
1596 return Err(DecodingError::Format(
1597 FormatErrorInner::InvalidColorBitDepth {
1598 color_type,
1599 bit_depth,
1600 }
1601 .into(),
1602 ));
1603 } else {
1604 color_type
1605 }
1606 }
1607 None => {
1608 return Err(DecodingError::Format(
1609 FormatErrorInner::InvalidColorType(color_type).into(),
1610 ))
1611 }
1612 };
1613 match buf.read_be()? {
1614 0u8 => (),
1616 n => {
1617 return Err(DecodingError::Format(
1618 FormatErrorInner::UnknownCompressionMethod(n).into(),
1619 ))
1620 }
1621 }
1622 match buf.read_be()? {
1623 0u8 => (),
1625 n => {
1626 return Err(DecodingError::Format(
1627 FormatErrorInner::UnknownFilterMethod(n).into(),
1628 ))
1629 }
1630 }
1631 let interlaced = match buf.read_be()? {
1632 0u8 => false,
1633 1 => true,
1634 n => {
1635 return Err(DecodingError::Format(
1636 FormatErrorInner::UnknownInterlaceMethod(n).into(),
1637 ))
1638 }
1639 };
1640
1641 if let Some(mut raw_row_len) = color_type.checked_raw_row_length(bit_depth, width) {
1642 if interlaced {
1643 raw_row_len = raw_row_len.saturating_mul(2);
1646 }
1647 self.inflater
1648 .set_max_total_output((height as usize).saturating_mul(raw_row_len));
1649 }
1650
1651 self.info = Some(Info {
1652 width,
1653 height,
1654 bit_depth,
1655 color_type,
1656 interlaced,
1657 ..Default::default()
1658 });
1659
1660 Ok(Decoded::Header(
1661 width, height, bit_depth, color_type, interlaced,
1662 ))
1663 }
1664
1665 fn split_keyword(buf: &[u8]) -> Result<(&[u8], &[u8]), DecodingError> {
1666 let null_byte_index = buf
1667 .iter()
1668 .position(|&b| b == 0)
1669 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?;
1670
1671 if null_byte_index == 0 || null_byte_index > 79 {
1672 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1673 }
1674
1675 Ok((&buf[..null_byte_index], &buf[null_byte_index + 1..]))
1676 }
1677
1678 fn parse_text(&mut self) -> Result<Decoded, DecodingError> {
1679 let buf = &self.current_chunk.raw_bytes[..];
1680 self.limits.reserve_bytes(buf.len())?;
1681
1682 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1683
1684 self.info
1685 .as_mut()
1686 .unwrap()
1687 .uncompressed_latin1_text
1688 .push(TEXtChunk::decode(keyword_slice, value_slice).map_err(DecodingError::from)?);
1689
1690 Ok(Decoded::Nothing)
1691 }
1692
1693 fn parse_ztxt(&mut self) -> Result<Decoded, DecodingError> {
1694 let buf = &self.current_chunk.raw_bytes[..];
1695 self.limits.reserve_bytes(buf.len())?;
1696
1697 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1698
1699 let compression_method = *value_slice
1700 .first()
1701 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1702
1703 let text_slice = &value_slice[1..];
1704
1705 self.info.as_mut().unwrap().compressed_latin1_text.push(
1706 ZTXtChunk::decode(keyword_slice, compression_method, text_slice)
1707 .map_err(DecodingError::from)?,
1708 );
1709
1710 Ok(Decoded::Nothing)
1711 }
1712
1713 fn parse_itxt(&mut self) -> Result<Decoded, DecodingError> {
1714 let buf = &self.current_chunk.raw_bytes[..];
1715 self.limits.reserve_bytes(buf.len())?;
1716
1717 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1718
1719 let compression_flag = *value_slice
1720 .first()
1721 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingCompressionFlag))?;
1722
1723 let compression_method = *value_slice
1724 .get(1)
1725 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1726
1727 let second_null_byte_index = value_slice[2..]
1728 .iter()
1729 .position(|&b| b == 0)
1730 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1731 + 2;
1732
1733 let language_tag_slice = &value_slice[2..second_null_byte_index];
1734
1735 let third_null_byte_index = value_slice[second_null_byte_index + 1..]
1736 .iter()
1737 .position(|&b| b == 0)
1738 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1739 + (second_null_byte_index + 1);
1740
1741 let translated_keyword_slice =
1742 &value_slice[second_null_byte_index + 1..third_null_byte_index];
1743
1744 let text_slice = &value_slice[third_null_byte_index + 1..];
1745
1746 self.info.as_mut().unwrap().utf8_text.push(
1747 ITXtChunk::decode(
1748 keyword_slice,
1749 compression_flag,
1750 compression_method,
1751 language_tag_slice,
1752 translated_keyword_slice,
1753 text_slice,
1754 )
1755 .map_err(DecodingError::from)?,
1756 );
1757
1758 Ok(Decoded::Nothing)
1759 }
1760
1761 fn parse_bkgd(&mut self) -> Decoded {
1765 let info = self.info.as_mut().unwrap();
1766 if info.bkgd.is_none() && !self.have_idat {
1767 let expected = match info.color_type {
1768 ColorType::Indexed => {
1769 if info.palette.is_none() {
1770 return Decoded::Nothing;
1771 };
1772 1
1773 }
1774 ColorType::Grayscale | ColorType::GrayscaleAlpha => 2,
1775 ColorType::Rgb | ColorType::Rgba => 6,
1776 };
1777 let vec = self.current_chunk.raw_bytes.clone();
1778 let len = vec.len();
1779 if len == expected {
1780 info.bkgd = Some(Cow::Owned(vec));
1781 }
1782 }
1783
1784 Decoded::Nothing
1785 }
1786}
1787
1788impl Info<'_> {
1789 fn validate(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1790 if fc.width == 0 || fc.height == 0 {
1791 return Err(DecodingError::Format(
1792 FormatErrorInner::InvalidDimensions.into(),
1793 ));
1794 }
1795
1796 let in_x_bounds = Some(fc.width) <= self.width.checked_sub(fc.x_offset);
1798 let in_y_bounds = Some(fc.height) <= self.height.checked_sub(fc.y_offset);
1800
1801 if !in_x_bounds || !in_y_bounds {
1802 return Err(DecodingError::Format(
1803 FormatErrorInner::BadSubFrameBounds {}.into(),
1805 ));
1806 }
1807
1808 Ok(())
1809 }
1810}
1811
1812impl Default for StreamingDecoder {
1813 fn default() -> Self {
1814 Self::new()
1815 }
1816}
1817
1818impl Default for ChunkState {
1819 fn default() -> Self {
1820 ChunkState {
1821 type_: ChunkType([0; 4]),
1822 crc: Crc32::new(),
1823 remaining: 0,
1824 raw_bytes: Vec::with_capacity(CHUNK_BUFFER_SIZE),
1825 }
1826 }
1827}
1828
1829#[cfg(test)]
1830mod tests {
1831 use super::ScaledFloat;
1832 use super::SourceChromaticities;
1833 use crate::test_utils::*;
1834 use crate::{Decoder, DecodingError, Reader};
1835 use approx::assert_relative_eq;
1836 use byteorder::WriteBytesExt;
1837 use std::borrow::Cow;
1838 use std::cell::RefCell;
1839 use std::collections::VecDeque;
1840 use std::fs::File;
1841 use std::io::{ErrorKind, Read, Write};
1842 use std::rc::Rc;
1843
1844 #[test]
1845 fn image_gamma() -> Result<(), ()> {
1846 fn trial(path: &str, expected: Option<ScaledFloat>) {
1847 let decoder = crate::Decoder::new(File::open(path).unwrap());
1848 let reader = decoder.read_info().unwrap();
1849 let actual: Option<ScaledFloat> = reader.info().source_gamma;
1850 assert!(actual == expected);
1851 }
1852 trial("tests/pngsuite/f00n0g08.png", None);
1853 trial("tests/pngsuite/f00n2c08.png", None);
1854 trial("tests/pngsuite/f01n0g08.png", None);
1855 trial("tests/pngsuite/f01n2c08.png", None);
1856 trial("tests/pngsuite/f02n0g08.png", None);
1857 trial("tests/pngsuite/f02n2c08.png", None);
1858 trial("tests/pngsuite/f03n0g08.png", None);
1859 trial("tests/pngsuite/f03n2c08.png", None);
1860 trial("tests/pngsuite/f04n0g08.png", None);
1861 trial("tests/pngsuite/f04n2c08.png", None);
1862 trial("tests/pngsuite/f99n0g04.png", None);
1863 trial("tests/pngsuite/tm3n3p02.png", None);
1864 trial("tests/pngsuite/g03n0g16.png", Some(ScaledFloat::new(0.35)));
1865 trial("tests/pngsuite/g03n2c08.png", Some(ScaledFloat::new(0.35)));
1866 trial("tests/pngsuite/g03n3p04.png", Some(ScaledFloat::new(0.35)));
1867 trial("tests/pngsuite/g04n0g16.png", Some(ScaledFloat::new(0.45)));
1868 trial("tests/pngsuite/g04n2c08.png", Some(ScaledFloat::new(0.45)));
1869 trial("tests/pngsuite/g04n3p04.png", Some(ScaledFloat::new(0.45)));
1870 trial("tests/pngsuite/g05n0g16.png", Some(ScaledFloat::new(0.55)));
1871 trial("tests/pngsuite/g05n2c08.png", Some(ScaledFloat::new(0.55)));
1872 trial("tests/pngsuite/g05n3p04.png", Some(ScaledFloat::new(0.55)));
1873 trial("tests/pngsuite/g07n0g16.png", Some(ScaledFloat::new(0.7)));
1874 trial("tests/pngsuite/g07n2c08.png", Some(ScaledFloat::new(0.7)));
1875 trial("tests/pngsuite/g07n3p04.png", Some(ScaledFloat::new(0.7)));
1876 trial("tests/pngsuite/g10n0g16.png", Some(ScaledFloat::new(1.0)));
1877 trial("tests/pngsuite/g10n2c08.png", Some(ScaledFloat::new(1.0)));
1878 trial("tests/pngsuite/g10n3p04.png", Some(ScaledFloat::new(1.0)));
1879 trial("tests/pngsuite/g25n0g16.png", Some(ScaledFloat::new(2.5)));
1880 trial("tests/pngsuite/g25n2c08.png", Some(ScaledFloat::new(2.5)));
1881 trial("tests/pngsuite/g25n3p04.png", Some(ScaledFloat::new(2.5)));
1882 Ok(())
1883 }
1884
1885 #[test]
1886 fn image_source_chromaticities() -> Result<(), ()> {
1887 fn trial(path: &str, expected: Option<SourceChromaticities>) {
1888 let decoder = crate::Decoder::new(File::open(path).unwrap());
1889 let reader = decoder.read_info().unwrap();
1890 let actual: Option<SourceChromaticities> = reader.info().source_chromaticities;
1891 assert!(actual == expected);
1892 }
1893 trial(
1894 "tests/pngsuite/ccwn2c08.png",
1895 Some(SourceChromaticities::new(
1896 (0.3127, 0.3290),
1897 (0.64, 0.33),
1898 (0.30, 0.60),
1899 (0.15, 0.06),
1900 )),
1901 );
1902 trial(
1903 "tests/pngsuite/ccwn3p08.png",
1904 Some(SourceChromaticities::new(
1905 (0.3127, 0.3290),
1906 (0.64, 0.33),
1907 (0.30, 0.60),
1908 (0.15, 0.06),
1909 )),
1910 );
1911 trial("tests/pngsuite/basi0g01.png", None);
1912 trial("tests/pngsuite/basi0g02.png", None);
1913 trial("tests/pngsuite/basi0g04.png", None);
1914 trial("tests/pngsuite/basi0g08.png", None);
1915 trial("tests/pngsuite/basi0g16.png", None);
1916 trial("tests/pngsuite/basi2c08.png", None);
1917 trial("tests/pngsuite/basi2c16.png", None);
1918 trial("tests/pngsuite/basi3p01.png", None);
1919 trial("tests/pngsuite/basi3p02.png", None);
1920 trial("tests/pngsuite/basi3p04.png", None);
1921 trial("tests/pngsuite/basi3p08.png", None);
1922 trial("tests/pngsuite/basi4a08.png", None);
1923 trial("tests/pngsuite/basi4a16.png", None);
1924 trial("tests/pngsuite/basi6a08.png", None);
1925 trial("tests/pngsuite/basi6a16.png", None);
1926 trial("tests/pngsuite/basn0g01.png", None);
1927 trial("tests/pngsuite/basn0g02.png", None);
1928 trial("tests/pngsuite/basn0g04.png", None);
1929 trial("tests/pngsuite/basn0g08.png", None);
1930 trial("tests/pngsuite/basn0g16.png", None);
1931 trial("tests/pngsuite/basn2c08.png", None);
1932 trial("tests/pngsuite/basn2c16.png", None);
1933 trial("tests/pngsuite/basn3p01.png", None);
1934 trial("tests/pngsuite/basn3p02.png", None);
1935 trial("tests/pngsuite/basn3p04.png", None);
1936 trial("tests/pngsuite/basn3p08.png", None);
1937 trial("tests/pngsuite/basn4a08.png", None);
1938 trial("tests/pngsuite/basn4a16.png", None);
1939 trial("tests/pngsuite/basn6a08.png", None);
1940 trial("tests/pngsuite/basn6a16.png", None);
1941 trial("tests/pngsuite/bgai4a08.png", None);
1942 trial("tests/pngsuite/bgai4a16.png", None);
1943 trial("tests/pngsuite/bgan6a08.png", None);
1944 trial("tests/pngsuite/bgan6a16.png", None);
1945 trial("tests/pngsuite/bgbn4a08.png", None);
1946 trial("tests/pngsuite/bggn4a16.png", None);
1947 trial("tests/pngsuite/bgwn6a08.png", None);
1948 trial("tests/pngsuite/bgyn6a16.png", None);
1949 trial("tests/pngsuite/cdfn2c08.png", None);
1950 trial("tests/pngsuite/cdhn2c08.png", None);
1951 trial("tests/pngsuite/cdsn2c08.png", None);
1952 trial("tests/pngsuite/cdun2c08.png", None);
1953 trial("tests/pngsuite/ch1n3p04.png", None);
1954 trial("tests/pngsuite/ch2n3p08.png", None);
1955 trial("tests/pngsuite/cm0n0g04.png", None);
1956 trial("tests/pngsuite/cm7n0g04.png", None);
1957 trial("tests/pngsuite/cm9n0g04.png", None);
1958 trial("tests/pngsuite/cs3n2c16.png", None);
1959 trial("tests/pngsuite/cs3n3p08.png", None);
1960 trial("tests/pngsuite/cs5n2c08.png", None);
1961 trial("tests/pngsuite/cs5n3p08.png", None);
1962 trial("tests/pngsuite/cs8n2c08.png", None);
1963 trial("tests/pngsuite/cs8n3p08.png", None);
1964 trial("tests/pngsuite/ct0n0g04.png", None);
1965 trial("tests/pngsuite/ct1n0g04.png", None);
1966 trial("tests/pngsuite/cten0g04.png", None);
1967 trial("tests/pngsuite/ctfn0g04.png", None);
1968 trial("tests/pngsuite/ctgn0g04.png", None);
1969 trial("tests/pngsuite/cthn0g04.png", None);
1970 trial("tests/pngsuite/ctjn0g04.png", None);
1971 trial("tests/pngsuite/ctzn0g04.png", None);
1972 trial("tests/pngsuite/f00n0g08.png", None);
1973 trial("tests/pngsuite/f00n2c08.png", None);
1974 trial("tests/pngsuite/f01n0g08.png", None);
1975 trial("tests/pngsuite/f01n2c08.png", None);
1976 trial("tests/pngsuite/f02n0g08.png", None);
1977 trial("tests/pngsuite/f02n2c08.png", None);
1978 trial("tests/pngsuite/f03n0g08.png", None);
1979 trial("tests/pngsuite/f03n2c08.png", None);
1980 trial("tests/pngsuite/f04n0g08.png", None);
1981 trial("tests/pngsuite/f04n2c08.png", None);
1982 trial("tests/pngsuite/f99n0g04.png", None);
1983 trial("tests/pngsuite/g03n0g16.png", None);
1984 trial("tests/pngsuite/g03n2c08.png", None);
1985 trial("tests/pngsuite/g03n3p04.png", None);
1986 trial("tests/pngsuite/g04n0g16.png", None);
1987 trial("tests/pngsuite/g04n2c08.png", None);
1988 trial("tests/pngsuite/g04n3p04.png", None);
1989 trial("tests/pngsuite/g05n0g16.png", None);
1990 trial("tests/pngsuite/g05n2c08.png", None);
1991 trial("tests/pngsuite/g05n3p04.png", None);
1992 trial("tests/pngsuite/g07n0g16.png", None);
1993 trial("tests/pngsuite/g07n2c08.png", None);
1994 trial("tests/pngsuite/g07n3p04.png", None);
1995 trial("tests/pngsuite/g10n0g16.png", None);
1996 trial("tests/pngsuite/g10n2c08.png", None);
1997 trial("tests/pngsuite/g10n3p04.png", None);
1998 trial("tests/pngsuite/g25n0g16.png", None);
1999 trial("tests/pngsuite/g25n2c08.png", None);
2000 trial("tests/pngsuite/g25n3p04.png", None);
2001 trial("tests/pngsuite/oi1n0g16.png", None);
2002 trial("tests/pngsuite/oi1n2c16.png", None);
2003 trial("tests/pngsuite/oi2n0g16.png", None);
2004 trial("tests/pngsuite/oi2n2c16.png", None);
2005 trial("tests/pngsuite/oi4n0g16.png", None);
2006 trial("tests/pngsuite/oi4n2c16.png", None);
2007 trial("tests/pngsuite/oi9n0g16.png", None);
2008 trial("tests/pngsuite/oi9n2c16.png", None);
2009 trial("tests/pngsuite/PngSuite.png", None);
2010 trial("tests/pngsuite/pp0n2c16.png", None);
2011 trial("tests/pngsuite/pp0n6a08.png", None);
2012 trial("tests/pngsuite/ps1n0g08.png", None);
2013 trial("tests/pngsuite/ps1n2c16.png", None);
2014 trial("tests/pngsuite/ps2n0g08.png", None);
2015 trial("tests/pngsuite/ps2n2c16.png", None);
2016 trial("tests/pngsuite/s01i3p01.png", None);
2017 trial("tests/pngsuite/s01n3p01.png", None);
2018 trial("tests/pngsuite/s02i3p01.png", None);
2019 trial("tests/pngsuite/s02n3p01.png", None);
2020 trial("tests/pngsuite/s03i3p01.png", None);
2021 trial("tests/pngsuite/s03n3p01.png", None);
2022 trial("tests/pngsuite/s04i3p01.png", None);
2023 trial("tests/pngsuite/s04n3p01.png", None);
2024 trial("tests/pngsuite/s05i3p02.png", None);
2025 trial("tests/pngsuite/s05n3p02.png", None);
2026 trial("tests/pngsuite/s06i3p02.png", None);
2027 trial("tests/pngsuite/s06n3p02.png", None);
2028 trial("tests/pngsuite/s07i3p02.png", None);
2029 trial("tests/pngsuite/s07n3p02.png", None);
2030 trial("tests/pngsuite/s08i3p02.png", None);
2031 trial("tests/pngsuite/s08n3p02.png", None);
2032 trial("tests/pngsuite/s09i3p02.png", None);
2033 trial("tests/pngsuite/s09n3p02.png", None);
2034 trial("tests/pngsuite/s32i3p04.png", None);
2035 trial("tests/pngsuite/s32n3p04.png", None);
2036 trial("tests/pngsuite/s33i3p04.png", None);
2037 trial("tests/pngsuite/s33n3p04.png", None);
2038 trial("tests/pngsuite/s34i3p04.png", None);
2039 trial("tests/pngsuite/s34n3p04.png", None);
2040 trial("tests/pngsuite/s35i3p04.png", None);
2041 trial("tests/pngsuite/s35n3p04.png", None);
2042 trial("tests/pngsuite/s36i3p04.png", None);
2043 trial("tests/pngsuite/s36n3p04.png", None);
2044 trial("tests/pngsuite/s37i3p04.png", None);
2045 trial("tests/pngsuite/s37n3p04.png", None);
2046 trial("tests/pngsuite/s38i3p04.png", None);
2047 trial("tests/pngsuite/s38n3p04.png", None);
2048 trial("tests/pngsuite/s39i3p04.png", None);
2049 trial("tests/pngsuite/s39n3p04.png", None);
2050 trial("tests/pngsuite/s40i3p04.png", None);
2051 trial("tests/pngsuite/s40n3p04.png", None);
2052 trial("tests/pngsuite/tbbn0g04.png", None);
2053 trial("tests/pngsuite/tbbn2c16.png", None);
2054 trial("tests/pngsuite/tbbn3p08.png", None);
2055 trial("tests/pngsuite/tbgn2c16.png", None);
2056 trial("tests/pngsuite/tbgn3p08.png", None);
2057 trial("tests/pngsuite/tbrn2c08.png", None);
2058 trial("tests/pngsuite/tbwn0g16.png", None);
2059 trial("tests/pngsuite/tbwn3p08.png", None);
2060 trial("tests/pngsuite/tbyn3p08.png", None);
2061 trial("tests/pngsuite/tm3n3p02.png", None);
2062 trial("tests/pngsuite/tp0n0g08.png", None);
2063 trial("tests/pngsuite/tp0n2c08.png", None);
2064 trial("tests/pngsuite/tp0n3p08.png", None);
2065 trial("tests/pngsuite/tp1n3p08.png", None);
2066 trial("tests/pngsuite/z00n2c08.png", None);
2067 trial("tests/pngsuite/z03n2c08.png", None);
2068 trial("tests/pngsuite/z06n2c08.png", None);
2069 Ok(())
2070 }
2071
2072 #[test]
2073 fn image_source_sbit() {
2074 fn trial(path: &str, expected: Option<Cow<[u8]>>) {
2075 let decoder = crate::Decoder::new(File::open(path).unwrap());
2076 let reader = decoder.read_info().unwrap();
2077 let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
2078 assert!(actual == expected);
2079 }
2080
2081 trial("tests/sbit/g.png", Some(Cow::Owned(vec![5u8])));
2082 trial("tests/sbit/ga.png", Some(Cow::Owned(vec![5u8, 3u8])));
2083 trial(
2084 "tests/sbit/indexed.png",
2085 Some(Cow::Owned(vec![5u8, 6u8, 5u8])),
2086 );
2087 trial("tests/sbit/rgb.png", Some(Cow::Owned(vec![5u8, 6u8, 5u8])));
2088 trial(
2089 "tests/sbit/rgba.png",
2090 Some(Cow::Owned(vec![5u8, 6u8, 5u8, 8u8])),
2091 );
2092 }
2093
2094 #[test]
2097 fn test_two_iccp_chunks() {
2098 let decoder = crate::Decoder::new(File::open("tests/bugfixes/issue#1825.png").unwrap());
2103 let reader = decoder.read_info().unwrap();
2104 let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
2105
2106 assert_eq!(4070462061, crc32fast::hash(&icc_profile));
2111 }
2112
2113 #[test]
2114 fn test_iccp_roundtrip() {
2115 let dummy_icc = b"I'm a profile";
2116
2117 let mut info = crate::Info::with_size(1, 1);
2118 info.icc_profile = Some(dummy_icc.into());
2119 let mut encoded_image = Vec::new();
2120 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2121 let mut enc = enc.write_header().unwrap();
2122 enc.write_image_data(&[0]).unwrap();
2123 enc.finish().unwrap();
2124
2125 let dec = crate::Decoder::new(encoded_image.as_slice());
2126 let dec = dec.read_info().unwrap();
2127 assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap());
2128 }
2129
2130 #[test]
2131 fn test_png_with_broken_iccp() {
2132 let decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
2133 assert!(decoder.read_info().is_ok());
2134 let mut decoder = crate::Decoder::new(File::open("tests/iccp/broken_iccp.png").unwrap());
2135 decoder.set_ignore_iccp_chunk(true);
2136 assert!(decoder.read_info().is_ok());
2137 }
2138
2139 #[test]
2141 fn test_mdcv_and_clli_chunks() {
2142 let decoder = crate::Decoder::new(File::open("tests/bugfixes/cicp_pq.png").unwrap());
2143 let reader = decoder.read_info().unwrap();
2144 let info = reader.info();
2145
2146 let cicp = info.coding_independent_code_points.unwrap();
2147 assert_eq!(cicp.color_primaries, 9);
2148 assert_eq!(cicp.transfer_function, 16);
2149 assert_eq!(cicp.matrix_coefficients, 0);
2150 assert!(cicp.is_video_full_range_image);
2151
2152 let mdcv = info.mastering_display_color_volume.unwrap();
2153 assert_relative_eq!(mdcv.chromaticities.red.0.into_value(), 0.680);
2154 assert_relative_eq!(mdcv.chromaticities.red.1.into_value(), 0.320);
2155 assert_relative_eq!(mdcv.chromaticities.green.0.into_value(), 0.265);
2156 assert_relative_eq!(mdcv.chromaticities.green.1.into_value(), 0.690);
2157 assert_relative_eq!(mdcv.chromaticities.blue.0.into_value(), 0.150);
2158 assert_relative_eq!(mdcv.chromaticities.blue.1.into_value(), 0.060);
2159 assert_relative_eq!(mdcv.chromaticities.white.0.into_value(), 0.3127);
2160 assert_relative_eq!(mdcv.chromaticities.white.1.into_value(), 0.3290);
2161 assert_relative_eq!(mdcv.min_luminance as f32 / 10_000.0, 0.01);
2162 assert_relative_eq!(mdcv.max_luminance as f32 / 10_000.0, 5000.0);
2163
2164 let clli = info.content_light_level.unwrap();
2165 assert_relative_eq!(clli.max_content_light_level as f32 / 10_000.0, 4000.0);
2166 assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0);
2167 }
2168
2169 #[test]
2171 fn test_finishing_twice() {
2172 let mut png = Vec::new();
2173 write_noncompressed_png(&mut png, 16, 1024);
2174 let decoder = Decoder::new(png.as_slice());
2175 let mut reader = decoder.read_info().unwrap();
2176
2177 reader.finish().unwrap();
2179
2180 let err = reader.finish().unwrap_err();
2182 assert!(matches!(&err, DecodingError::Parameter(_)));
2183 assert_eq!("End of image has been reached", format!("{err}"));
2184 }
2185
2186 fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) {
2189 let mut data = Vec::new();
2190 data.write_u32::<byteorder::BigEndian>(animation.num_frames)
2191 .unwrap();
2192 data.write_u32::<byteorder::BigEndian>(animation.num_plays)
2193 .unwrap();
2194 write_chunk(w, b"acTL", &data);
2195 }
2196
2197 fn write_fctl(w: &mut impl Write, frame: &crate::FrameControl) {
2200 let mut data = Vec::new();
2201 data.write_u32::<byteorder::BigEndian>(frame.sequence_number)
2202 .unwrap();
2203 data.write_u32::<byteorder::BigEndian>(frame.width).unwrap();
2204 data.write_u32::<byteorder::BigEndian>(frame.height)
2205 .unwrap();
2206 data.write_u32::<byteorder::BigEndian>(frame.x_offset)
2207 .unwrap();
2208 data.write_u32::<byteorder::BigEndian>(frame.y_offset)
2209 .unwrap();
2210 data.write_u16::<byteorder::BigEndian>(frame.delay_num)
2211 .unwrap();
2212 data.write_u16::<byteorder::BigEndian>(frame.delay_den)
2213 .unwrap();
2214 data.write_u8(frame.dispose_op as u8).unwrap();
2215 data.write_u8(frame.blend_op as u8).unwrap();
2216 write_chunk(w, b"fcTL", &data);
2217 }
2218
2219 fn write_fdat(w: &mut impl Write, sequence_number: u32, image_data: &[u8]) {
2222 let mut data = Vec::new();
2223 data.write_u32::<byteorder::BigEndian>(sequence_number)
2224 .unwrap();
2225 data.write_all(image_data).unwrap();
2226 write_chunk(w, b"fdAT", &data);
2227 }
2228
2229 fn write_fdat_prefix(w: &mut impl Write, num_frames: u32, width: u32) {
2234 write_png_sig(w);
2235 write_rgba8_ihdr_with_width(w, width);
2236 write_actl(
2237 w,
2238 &crate::AnimationControl {
2239 num_frames,
2240 num_plays: 0,
2241 },
2242 );
2243
2244 let mut fctl = crate::FrameControl {
2245 width,
2246 height: width,
2247 ..Default::default()
2248 };
2249 write_fctl(w, &fctl);
2250 write_rgba8_idats(w, width, 0x7fffffff);
2251
2252 fctl.sequence_number += 1;
2253 write_fctl(w, &fctl);
2254 }
2255
2256 #[test]
2257 fn test_fdat_chunk_payload_length_0() {
2258 let mut png = Vec::new();
2259 write_fdat_prefix(&mut png, 2, 8);
2260 write_chunk(&mut png, b"fdAT", &[]);
2261
2262 let decoder = Decoder::new(png.as_slice());
2263 let mut reader = decoder.read_info().unwrap();
2264 let mut buf = vec![0; reader.output_buffer_size()];
2265 reader.next_frame(&mut buf).unwrap();
2266
2267 let err = reader.next_frame(&mut buf).unwrap_err();
2269 assert!(matches!(&err, DecodingError::Format(_)));
2270 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2271
2272 let err2 = reader.next_frame(&mut buf).unwrap_err();
2277 assert!(matches!(&err2, DecodingError::Parameter(_)));
2278 assert_eq!(
2279 "A fatal decoding error has been encounted earlier",
2280 format!("{err2}")
2281 );
2282 }
2283
2284 #[test]
2285 fn test_fdat_chunk_payload_length_3() {
2286 let mut png = Vec::new();
2287 write_fdat_prefix(&mut png, 2, 8);
2288 write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
2289
2290 let decoder = Decoder::new(png.as_slice());
2291 let mut reader = decoder.read_info().unwrap();
2292 let mut buf = vec![0; reader.output_buffer_size()];
2293 reader.next_frame(&mut buf).unwrap();
2294
2295 let err = reader.next_frame(&mut buf).unwrap_err();
2297 assert!(matches!(&err, DecodingError::Format(_)));
2298 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2299 }
2300
2301 #[test]
2302 fn test_frame_split_across_two_fdat_chunks() {
2303 let png = {
2318 let mut png = Vec::new();
2319 write_fdat_prefix(&mut png, 2, 8);
2320 let image_data = generate_rgba8_with_width_and_height(8, 8);
2321 write_fdat(&mut png, 2, &image_data[..30]);
2322 write_fdat(&mut png, 3, &image_data[30..]);
2323 write_iend(&mut png);
2324 png
2325 };
2326
2327 let decoder = Decoder::new(png.as_slice());
2329 let mut reader = decoder.read_info().unwrap();
2330 let mut buf = vec![0; reader.output_buffer_size()];
2331 let Some(animation_control) = reader.info().animation_control else {
2332 panic!("No acTL");
2333 };
2334 assert_eq!(animation_control.num_frames, 2);
2335
2336 let first_frame: Vec<u8>;
2338 {
2339 reader.next_frame(&mut buf).unwrap();
2340 first_frame = buf.clone();
2341
2342 let Some(frame_control) = reader.info().frame_control else {
2346 panic!("No fcTL (1st frame)");
2347 };
2348 assert_eq!(frame_control.sequence_number, 0);
2351 }
2352
2353 let second_frame: Vec<u8>;
2355 {
2356 reader.next_frame(&mut buf).unwrap();
2357 second_frame = buf.clone();
2358
2359 let Some(frame_control) = reader.info().frame_control else {
2361 panic!("No fcTL (2nd frame)");
2362 };
2363 assert_eq!(frame_control.sequence_number, 1);
2367 }
2368
2369 assert_eq!(first_frame, second_frame);
2370 }
2371
2372 #[test]
2373 fn test_idat_bigger_than_image_size_from_ihdr() {
2374 let png = {
2375 let mut png = Vec::new();
2376 write_png_sig(&mut png);
2377 write_rgba8_ihdr_with_width(&mut png, 8);
2378
2379 write_chunk(
2383 &mut png,
2384 b"IDAT",
2385 &generate_rgba8_with_width_and_height(8, 256),
2386 );
2387
2388 write_iend(&mut png);
2389 png
2390 };
2391 let decoder = Decoder::new(png.as_slice());
2392 let mut reader = decoder.read_info().unwrap();
2393 let mut buf = vec![0; reader.output_buffer_size()];
2394
2395 reader.next_frame(&mut buf).unwrap();
2398 assert_eq!(3093270825, crc32fast::hash(&buf));
2399 }
2400
2401 #[test]
2402 fn test_only_idat_chunk_in_input_stream() {
2403 let png = {
2404 let mut png = Vec::new();
2405 write_png_sig(&mut png);
2406 write_chunk(&mut png, b"IDAT", &[]);
2407 png
2408 };
2409 let decoder = Decoder::new(png.as_slice());
2410 let Err(err) = decoder.read_info() else {
2411 panic!("Expected an error")
2412 };
2413 assert!(matches!(&err, DecodingError::Format(_)));
2414 assert_eq!(
2415 "ChunkType { type: IDAT, \
2416 critical: true, \
2417 private: false, \
2418 reserved: false, \
2419 safecopy: false \
2420 } chunk appeared before IHDR chunk",
2421 format!("{err}"),
2422 );
2423 }
2424
2425 #[derive(Clone)]
2428 struct StreamingInput(Rc<RefCell<StreamingInputState>>);
2429
2430 struct StreamingInputState {
2431 full_input: Vec<u8>,
2432 current_pos: usize,
2433 available_len: usize,
2434 }
2435
2436 impl StreamingInput {
2437 fn new(full_input: Vec<u8>) -> Self {
2438 Self(Rc::new(RefCell::new(StreamingInputState {
2439 full_input,
2440 current_pos: 0,
2441 available_len: 0,
2442 })))
2443 }
2444
2445 fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
2446 let mut png = Vec::new();
2447 write_noncompressed_png(&mut png, width, idat_size);
2448 Self::new(png)
2449 }
2450
2451 fn expose_next_byte(&self) {
2452 let mut state = self.0.borrow_mut();
2453 assert!(state.available_len < state.full_input.len());
2454 state.available_len += 1;
2455 }
2456
2457 fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
2458 loop {
2459 self.0.borrow_mut().current_pos = 0;
2460 match Decoder::new(self.clone()).read_info() {
2461 Ok(reader) => {
2462 break reader;
2463 }
2464 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2465 self.expose_next_byte();
2466 }
2467 _ => panic!("Unexpected error"),
2468 }
2469 }
2470 }
2471
2472 fn decode_full_input<F, R>(&self, f: F) -> R
2473 where
2474 F: FnOnce(Reader<&[u8]>) -> R,
2475 {
2476 let state = self.0.borrow();
2477 let decoder = Decoder::new(state.full_input.as_slice());
2478 f(decoder.read_info().unwrap())
2479 }
2480 }
2481
2482 impl Read for StreamingInput {
2483 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
2484 let mut state = self.0.borrow_mut();
2485 let mut available_bytes = &state.full_input[state.current_pos..state.available_len];
2486 let number_of_read_bytes = available_bytes.read(buf)?;
2487 state.current_pos += number_of_read_bytes;
2488 assert!(state.current_pos <= state.available_len);
2489 Ok(number_of_read_bytes)
2490 }
2491 }
2492
2493 #[test]
2495 fn test_streaming_input_and_decoding_via_next_frame() {
2496 const WIDTH: u32 = 16;
2497 const IDAT_SIZE: usize = 512;
2498 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2499
2500 let (whole_output_info, decoded_from_whole_input) =
2501 streaming_input.decode_full_input(|mut r| {
2502 let mut buf = vec![0; r.output_buffer_size()];
2503 let output_info = r.next_frame(&mut buf).unwrap();
2504 (output_info, buf)
2505 });
2506
2507 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2508 let mut decoded_from_streaming_input = vec![0; png_reader.output_buffer_size()];
2509 let streaming_output_info = loop {
2510 match png_reader.next_frame(decoded_from_streaming_input.as_mut_slice()) {
2511 Ok(output_info) => break output_info,
2512 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2513 streaming_input.expose_next_byte()
2514 }
2515 e => panic!("Unexpected error: {:?}", e),
2516 }
2517 };
2518 assert_eq!(whole_output_info, streaming_output_info);
2519 assert_eq!(
2520 crc32fast::hash(&decoded_from_whole_input),
2521 crc32fast::hash(&decoded_from_streaming_input)
2522 );
2523 }
2524
2525 #[test]
2527 fn test_streaming_input_and_decoding_via_next_row() {
2528 const WIDTH: u32 = 16;
2529 const IDAT_SIZE: usize = 512;
2530 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2531
2532 let decoded_from_whole_input = streaming_input.decode_full_input(|mut r| {
2533 let mut buf = vec![0; r.output_buffer_size()];
2534 r.next_frame(&mut buf).unwrap();
2535 buf
2536 });
2537
2538 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2539 let mut decoded_from_streaming_input = Vec::new();
2540 loop {
2541 match png_reader.next_row() {
2542 Ok(None) => break,
2543 Ok(Some(row)) => decoded_from_streaming_input.extend_from_slice(row.data()),
2544 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2545 streaming_input.expose_next_byte()
2546 }
2547 e => panic!("Unexpected error: {:?}", e),
2548 }
2549 }
2550 assert_eq!(
2551 crc32fast::hash(&decoded_from_whole_input),
2552 crc32fast::hash(&decoded_from_streaming_input)
2553 );
2554 }
2555
2556 #[test]
2558 fn test_streaming_input_and_reading_header_info() {
2559 const WIDTH: u32 = 16;
2560 const IDAT_SIZE: usize = 512;
2561 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2562
2563 let info_from_whole_input = streaming_input.decode_full_input(|r| r.info().clone());
2564
2565 let mut decoder = Decoder::new(streaming_input.clone());
2566 let info_from_streaming_input = loop {
2567 match decoder.read_header_info() {
2568 Ok(info) => break info.clone(),
2569 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2570 streaming_input.expose_next_byte()
2571 }
2572 e => panic!("Unexpected error: {:?}", e),
2573 }
2574 };
2575
2576 assert_eq!(info_from_whole_input.width, info_from_streaming_input.width);
2577 assert_eq!(
2578 info_from_whole_input.height,
2579 info_from_streaming_input.height
2580 );
2581 assert_eq!(
2582 info_from_whole_input.bit_depth,
2583 info_from_streaming_input.bit_depth
2584 );
2585 assert_eq!(
2586 info_from_whole_input.color_type,
2587 info_from_streaming_input.color_type
2588 );
2589 assert_eq!(
2590 info_from_whole_input.interlaced,
2591 info_from_streaming_input.interlaced
2592 );
2593 }
2594
2595 fn create_reader_of_ihdr_idat() -> Reader<VecDeque<u8>> {
2598 let mut png = VecDeque::new();
2599 write_noncompressed_png(&mut png, 16, 1024);
2600 Decoder::new(png).read_info().unwrap()
2601 }
2602
2603 fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<VecDeque<u8>> {
2606 let idat_width = 16;
2607 let mut fctl = crate::FrameControl {
2608 width: idat_width,
2609 height: idat_width, ..Default::default()
2611 };
2612
2613 let mut png = VecDeque::new();
2614 write_png_sig(&mut png);
2615 write_rgba8_ihdr_with_width(&mut png, idat_width);
2616 write_actl(
2617 &mut png,
2618 &crate::AnimationControl {
2619 num_frames: 2,
2620 num_plays: 0,
2621 },
2622 );
2623 fctl.sequence_number = 0;
2624 write_fctl(&mut png, &fctl);
2625 let idat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height + 1);
2629 write_chunk(&mut png, b"IDAT", &idat_data);
2630
2631 let fdat_width = 10;
2632 fctl.sequence_number = 1;
2633 fctl.width = fdat_width;
2637 write_fctl(&mut png, &fctl);
2638 let fdat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height);
2639 write_fdat(&mut png, 2, &fdat_data);
2640 write_iend(&mut png);
2641
2642 Decoder::new(png).read_info().unwrap()
2643 }
2644
2645 fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<VecDeque<u8>> {
2648 let width = 16;
2649 let frame_data = generate_rgba8_with_width_and_height(width, width);
2650 let mut fctl = crate::FrameControl {
2651 width,
2652 height: width,
2653 ..Default::default()
2654 };
2655
2656 let mut png = VecDeque::new();
2657 write_png_sig(&mut png);
2658 write_rgba8_ihdr_with_width(&mut png, width);
2659 write_actl(
2660 &mut png,
2661 &crate::AnimationControl {
2662 num_frames: 2,
2663 num_plays: 0,
2664 },
2665 );
2666 write_chunk(&mut png, b"IDAT", &frame_data);
2667 fctl.sequence_number = 0;
2668 write_fctl(&mut png, &fctl);
2669 write_fdat(&mut png, 1, &frame_data);
2670 fctl.sequence_number = 2;
2671 write_fctl(&mut png, &fctl);
2672 write_fdat(&mut png, 3, &frame_data);
2673 write_iend(&mut png);
2674
2675 Decoder::new(png).read_info().unwrap()
2676 }
2677
2678 fn get_fctl_sequence_number(reader: &Reader<impl Read>) -> u32 {
2679 reader
2680 .info()
2681 .frame_control
2682 .as_ref()
2683 .unwrap()
2684 .sequence_number
2685 }
2686
2687 #[test]
2690 fn test_next_frame_polling_after_end_non_animated() {
2691 let mut reader = create_reader_of_ihdr_idat();
2692 let mut buf = vec![0; reader.output_buffer_size()];
2693 reader
2694 .next_frame(&mut buf)
2695 .expect("Expecting no error for IDAT frame");
2696
2697 let err = reader
2698 .next_frame(&mut buf)
2699 .expect_err("Main test - expecting error");
2700 assert!(
2701 matches!(&err, DecodingError::Parameter(_)),
2702 "Unexpected kind of error: {:?}",
2703 &err,
2704 );
2705 }
2706
2707 #[test]
2710 fn test_next_frame_info_polling_after_end_non_animated() {
2711 let mut reader = create_reader_of_ihdr_idat();
2712
2713 let err = reader
2714 .next_frame_info()
2715 .expect_err("Main test - expecting error");
2716 assert!(
2717 matches!(&err, DecodingError::Parameter(_)),
2718 "Unexpected kind of error: {:?}",
2719 &err,
2720 );
2721 }
2722
2723 #[test]
2727 fn test_next_frame_polling_after_end_idat_part_of_animation() {
2728 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2729 let mut buf = vec![0; reader.output_buffer_size()];
2730
2731 assert_eq!(get_fctl_sequence_number(&reader), 0);
2732 reader
2733 .next_frame(&mut buf)
2734 .expect("Expecting no error for IDAT frame");
2735
2736 assert_eq!(get_fctl_sequence_number(&reader), 0);
2738
2739 reader
2740 .next_frame(&mut buf)
2741 .expect("Expecting no error for fdAT frame");
2742 assert_eq!(get_fctl_sequence_number(&reader), 1);
2743
2744 let err = reader
2745 .next_frame(&mut buf)
2746 .expect_err("Main test - expecting error");
2747 assert!(
2748 matches!(&err, DecodingError::Parameter(_)),
2749 "Unexpected kind of error: {:?}",
2750 &err,
2751 );
2752 }
2753
2754 #[test]
2758 fn test_next_frame_polling_after_end_idat_not_part_of_animation() {
2759 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
2760 let mut buf = vec![0; reader.output_buffer_size()];
2761
2762 assert!(reader.info().frame_control.is_none());
2763 reader
2764 .next_frame(&mut buf)
2765 .expect("Expecting no error for IDAT frame");
2766
2767 assert!(reader.info().frame_control.is_none());
2769
2770 reader
2771 .next_frame(&mut buf)
2772 .expect("Expecting no error for 1st fdAT frame");
2773 assert_eq!(get_fctl_sequence_number(&reader), 0);
2774
2775 reader
2776 .next_frame(&mut buf)
2777 .expect("Expecting no error for 2nd fdAT frame");
2778 assert_eq!(get_fctl_sequence_number(&reader), 2);
2779
2780 let err = reader
2781 .next_frame(&mut buf)
2782 .expect_err("Main test - expecting error");
2783 assert!(
2784 matches!(&err, DecodingError::Parameter(_)),
2785 "Unexpected kind of error: {:?}",
2786 &err,
2787 );
2788 }
2789
2790 #[test]
2793 fn test_row_by_row_then_next_frame() {
2794 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2795 let mut buf = vec![0; reader.output_buffer_size()];
2796
2797 assert_eq!(get_fctl_sequence_number(&reader), 0);
2798 while let Some(_) = reader.next_row().unwrap() {}
2799 assert_eq!(get_fctl_sequence_number(&reader), 0);
2800
2801 buf.fill(0x0f);
2802 reader
2803 .next_frame(&mut buf)
2804 .expect("Expecting no error from next_frame call");
2805
2806 assert_eq!(get_fctl_sequence_number(&reader), 1);
2808 assert!(buf.iter().any(|byte| *byte != 0x0f));
2809 }
2810
2811 #[test]
2815 fn test_row_by_row_of_two_frames() {
2816 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2817
2818 let mut rows_of_frame1 = 0;
2819 assert_eq!(get_fctl_sequence_number(&reader), 0);
2820 while let Some(_) = reader.next_row().unwrap() {
2821 rows_of_frame1 += 1;
2822 }
2823 assert_eq!(rows_of_frame1, 16);
2824 assert_eq!(get_fctl_sequence_number(&reader), 0);
2825
2826 let mut rows_of_frame2 = 0;
2827 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
2828 assert_eq!(get_fctl_sequence_number(&reader), 1);
2829 while let Some(_) = reader.next_row().unwrap() {
2830 rows_of_frame2 += 1;
2831 }
2832 assert_eq!(rows_of_frame2, 16);
2833 assert_eq!(get_fctl_sequence_number(&reader), 1);
2834
2835 let err = reader
2836 .next_frame_info()
2837 .expect_err("No more frames - expecting error");
2838 assert!(
2839 matches!(&err, DecodingError::Parameter(_)),
2840 "Unexpected kind of error: {:?}",
2841 &err,
2842 );
2843 }
2844
2845 #[test]
2851 fn test_next_frame_info_after_next_frame() {
2852 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2853 let mut buf = vec![0; reader.output_buffer_size()];
2854
2855 assert_eq!(get_fctl_sequence_number(&reader), 0);
2856 reader
2857 .next_frame(&mut buf)
2858 .expect("Expecting no error for IDAT frame");
2859
2860 assert_eq!(get_fctl_sequence_number(&reader), 0);
2862
2863 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
2865 assert_eq!(get_fctl_sequence_number(&reader), 1);
2866
2867 reader
2868 .next_frame(&mut buf)
2869 .expect("Expecting no error for fdAT frame");
2870 assert_eq!(get_fctl_sequence_number(&reader), 1);
2871
2872 let err = reader
2873 .next_frame_info()
2874 .expect_err("Main test - expecting error");
2875 assert!(
2876 matches!(&err, DecodingError::Parameter(_)),
2877 "Unexpected kind of error: {:?}",
2878 &err,
2879 );
2880 }
2881
2882 #[test]
2885 fn test_next_frame_info_to_skip_first_frame() {
2886 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
2887 let mut buf = vec![0; reader.output_buffer_size()];
2888
2889 assert!(reader.info().frame_control.is_none());
2892
2893 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 0);
2896 assert_eq!(get_fctl_sequence_number(&reader), 0);
2897 reader
2898 .next_frame(&mut buf)
2899 .expect("Expecting no error for 1st fdAT frame");
2900 assert_eq!(get_fctl_sequence_number(&reader), 0);
2901
2902 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 2);
2904 reader
2905 .next_frame(&mut buf)
2906 .expect("Expecting no error for 2nd fdAT frame");
2907 assert_eq!(get_fctl_sequence_number(&reader), 2);
2908
2909 let err = reader
2910 .next_frame_info()
2911 .expect_err("Main test - expecting error");
2912 assert!(
2913 matches!(&err, DecodingError::Parameter(_)),
2914 "Unexpected kind of error: {:?}",
2915 &err,
2916 );
2917 }
2918}