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::UnfilterBuf;
10use super::zlib::ZlibStream;
11use crate::chunk::is_critical;
12use crate::chunk::{self, ChunkType, IDAT, IEND, IHDR};
13use crate::common::{
14 AnimationControl, BitDepth, BlendOp, ColorType, ContentLightLevelInfo, DisposeOp, FrameControl,
15 Info, MasteringDisplayColorVolume, ParameterError, ParameterErrorKind, PixelDimensions,
16 ScaledFloat, SourceChromaticities, Unit,
17};
18use crate::text_metadata::{ITXtChunk, TEXtChunk, TextDecodingError, ZTXtChunk};
19use crate::traits::ReadBytesExt;
20use crate::{CodingIndependentCodePoints, Limits};
21
22pub const CHUNK_BUFFER_SIZE: usize = 128;
23
24#[allow(unexpected_cfgs)]
29const CHECKSUM_DISABLED: bool = cfg!(fuzzing);
30
31#[derive(Debug)]
33enum U32ValueKind {
34 Signature1stU32,
37 Signature2ndU32,
40 Length,
43 Type { length: u32 },
46 Crc(ChunkType),
49 ApngSequenceNumber,
52}
53
54#[derive(Debug)]
55enum State {
56 U32 {
60 kind: U32ValueKind,
61 bytes: [u8; 4],
62 accumulated_count: usize,
63 },
64 ReadChunkData(ChunkType),
67 ImageData(ChunkType),
70}
71
72impl State {
73 fn new_u32(kind: U32ValueKind) -> Self {
74 Self::U32 {
75 kind,
76 bytes: [0; 4],
77 accumulated_count: 0,
78 }
79 }
80}
81
82#[derive(Debug)]
83pub enum Decoded {
85 Nothing,
87
88 ChunkBegin(u32, ChunkType),
90
91 ChunkComplete(ChunkType),
93
94 BadAncillaryChunk(ChunkType),
97
98 SkippedAncillaryChunk(ChunkType),
101
102 ImageData,
104
105 ImageDataFlushed,
109}
110
111#[derive(Debug)]
117pub enum DecodingError {
118 IoError(io::Error),
125 Format(FormatError),
132 Parameter(ParameterError),
148 LimitsExceeded,
156}
157
158#[derive(Debug)]
159pub struct FormatError {
160 inner: FormatErrorInner,
161}
162
163#[derive(Debug)]
164pub(crate) enum FormatErrorInner {
165 CrcMismatch {
167 crc_val: u32,
169 crc_sum: u32,
171 chunk: ChunkType,
173 },
174 InvalidSignature,
176 MissingFctl,
179 MissingImageData,
181 ChunkBeforeIhdr {
183 kind: ChunkType,
184 },
185 AfterIdat {
187 kind: ChunkType,
188 },
189 BeforePlte {
191 kind: ChunkType,
192 },
193 AfterPlte {
195 kind: ChunkType,
196 },
197 OutsidePlteIdat {
199 kind: ChunkType,
200 },
201 DuplicateChunk {
203 kind: ChunkType,
204 },
205 ApngOrder {
207 present: u32,
209 expected: u32,
211 },
212 ShortPalette {
215 expected: usize,
216 len: usize,
217 },
218 InvalidSbitChunkSize {
220 color_type: ColorType,
221 expected: usize,
222 len: usize,
223 },
224 InvalidSbit {
225 sample_depth: BitDepth,
226 sbit: u8,
227 },
228 PaletteRequired,
230 InvalidColorBitDepth {
232 color_type: ColorType,
233 bit_depth: BitDepth,
234 },
235 ColorWithBadTrns(ColorType),
236 InvalidDimensions,
238 InvalidBitDepth(u8),
239 InvalidColorType(u8),
240 InvalidDisposeOp(u8),
241 InvalidBlendOp(u8),
242 InvalidUnit(u8),
243 InvalidSrgbRenderingIntent(u8),
245 UnknownCompressionMethod(u8),
246 UnknownFilterMethod(u8),
247 UnknownInterlaceMethod(u8),
248 BadSubFrameBounds {},
251 CorruptFlateStream {
254 err: fdeflate::DecompressionError,
255 },
256 NoMoreImageData,
258 BadTextEncoding(TextDecodingError),
260 FdatShorterThanFourBytes,
262 UnexpectedRestartOfDataChunkSequence {
271 kind: ChunkType,
272 },
273 ChunkTooShort {
275 kind: ChunkType,
276 },
277 UnrecognizedCriticalChunk {
278 type_str: ChunkType,
280 },
281 BadGammaValue,
282}
283
284impl error::Error for DecodingError {
285 fn cause(&self) -> Option<&(dyn error::Error + 'static)> {
286 match self {
287 DecodingError::IoError(err) => Some(err),
288 _ => None,
289 }
290 }
291}
292
293impl fmt::Display for DecodingError {
294 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
295 use self::DecodingError::*;
296 match self {
297 IoError(err) => write!(fmt, "{}", err),
298 Parameter(desc) => write!(fmt, "{}", &desc),
299 Format(desc) => write!(fmt, "{}", desc),
300 LimitsExceeded => write!(fmt, "limits are exceeded"),
301 }
302 }
303}
304
305impl fmt::Display for FormatError {
306 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
307 use FormatErrorInner::*;
308 match &self.inner {
309 CrcMismatch {
310 crc_val,
311 crc_sum,
312 chunk,
313 ..
314 } => write!(
315 fmt,
316 "CRC error: expected 0x{:x} have 0x{:x} while decoding {:?} chunk.",
317 crc_val, crc_sum, chunk
318 ),
319 MissingFctl => write!(fmt, "fcTL chunk missing before fdAT chunk."),
320 MissingImageData => write!(fmt, "IDAT or fdAT chunk is missing."),
321 ChunkBeforeIhdr { kind } => write!(fmt, "{:?} chunk appeared before IHDR chunk", kind),
322 AfterIdat { kind } => write!(fmt, "Chunk {:?} is invalid after IDAT chunk.", kind),
323 BeforePlte { kind } => write!(fmt, "Chunk {:?} is invalid before PLTE chunk.", kind),
324 AfterPlte { kind } => write!(fmt, "Chunk {:?} is invalid after PLTE chunk.", kind),
325 OutsidePlteIdat { kind } => write!(
326 fmt,
327 "Chunk {:?} must appear between PLTE and IDAT chunks.",
328 kind
329 ),
330 DuplicateChunk { kind } => write!(fmt, "Chunk {:?} must appear at most once.", kind),
331 ApngOrder { present, expected } => write!(
332 fmt,
333 "Sequence is not in order, expected #{} got #{}.",
334 expected, present,
335 ),
336 ShortPalette { expected, len } => write!(
337 fmt,
338 "Not enough palette entries, expect {} got {}.",
339 expected, len
340 ),
341 InvalidSbitChunkSize {color_type, expected, len} => write!(
342 fmt,
343 "The size of the sBIT chunk should be {} byte(s), but {} byte(s) were provided for the {:?} color type.",
344 expected, len, color_type
345 ),
346 InvalidSbit {sample_depth, sbit} => write!(
347 fmt,
348 "Invalid sBIT value {}. It must be greater than zero and less than the sample depth {:?}.",
349 sbit, sample_depth
350 ),
351 PaletteRequired => write!(fmt, "Missing palette of indexed image."),
352 InvalidDimensions => write!(fmt, "Invalid image dimensions"),
353 InvalidColorBitDepth {
354 color_type,
355 bit_depth,
356 } => write!(
357 fmt,
358 "Invalid color/depth combination in header: {:?}/{:?}",
359 color_type, bit_depth,
360 ),
361 ColorWithBadTrns(color_type) => write!(
362 fmt,
363 "Transparency chunk found for color type {:?}.",
364 color_type
365 ),
366 InvalidBitDepth(nr) => write!(fmt, "Invalid bit depth {}.", nr),
367 InvalidColorType(nr) => write!(fmt, "Invalid color type {}.", nr),
368 InvalidDisposeOp(nr) => write!(fmt, "Invalid dispose op {}.", nr),
369 InvalidBlendOp(nr) => write!(fmt, "Invalid blend op {}.", nr),
370 InvalidUnit(nr) => write!(fmt, "Invalid physical pixel size unit {}.", nr),
371 InvalidSrgbRenderingIntent(nr) => write!(fmt, "Invalid sRGB rendering intent {}.", nr),
372 UnknownCompressionMethod(nr) => write!(fmt, "Unknown compression method {}.", nr),
373 UnknownFilterMethod(nr) => write!(fmt, "Unknown filter method {}.", nr),
374 UnknownInterlaceMethod(nr) => write!(fmt, "Unknown interlace method {}.", nr),
375 BadSubFrameBounds {} => write!(fmt, "Sub frame is out-of-bounds."),
376 InvalidSignature => write!(fmt, "Invalid PNG signature."),
377 NoMoreImageData => write!(
378 fmt,
379 "IDAT or fDAT chunk does not have enough data for image."
380 ),
381 CorruptFlateStream { err } => {
382 write!(fmt, "Corrupt deflate stream. ")?;
383 write!(fmt, "{:?}", err)
384 }
385 BadTextEncoding(tde) => {
387 match tde {
388 TextDecodingError::Unrepresentable => {
389 write!(fmt, "Unrepresentable data in tEXt chunk.")
390 }
391 TextDecodingError::InvalidKeywordSize => {
392 write!(fmt, "Keyword empty or longer than 79 bytes.")
393 }
394 TextDecodingError::MissingNullSeparator => {
395 write!(fmt, "No null separator in tEXt chunk.")
396 }
397 TextDecodingError::InflationError => {
398 write!(fmt, "Invalid compressed text data.")
399 }
400 TextDecodingError::OutOfDecompressionSpace => {
401 write!(fmt, "Out of decompression space. Try with a larger limit.")
402 }
403 TextDecodingError::InvalidCompressionMethod => {
404 write!(fmt, "Using an unrecognized byte as compression method.")
405 }
406 TextDecodingError::InvalidCompressionFlag => {
407 write!(fmt, "Using a flag that is not 0 or 255 as a compression flag for iTXt chunk.")
408 }
409 TextDecodingError::MissingCompressionFlag => {
410 write!(fmt, "No compression flag in the iTXt chunk.")
411 }
412 }
413 }
414 FdatShorterThanFourBytes => write!(fmt, "fdAT chunk shorter than 4 bytes"),
415 UnexpectedRestartOfDataChunkSequence { kind } => {
416 write!(fmt, "Unexpected restart of {:?} chunk sequence", kind)
417 }
418 ChunkTooShort { kind } => {
419 write!(fmt, "Chunk is too short: {:?}", kind)
420 }
421 UnrecognizedCriticalChunk { type_str } => {
422 write!(fmt, "Unrecognized critical chunk: {:?}", type_str)
423 }
424 BadGammaValue => write!(fmt, "Bad gamma value."),
425 }
426 }
427}
428
429impl From<io::Error> for DecodingError {
430 fn from(err: io::Error) -> DecodingError {
431 DecodingError::IoError(err)
432 }
433}
434
435impl From<FormatError> for DecodingError {
436 fn from(err: FormatError) -> DecodingError {
437 DecodingError::Format(err)
438 }
439}
440
441impl From<FormatErrorInner> for FormatError {
442 fn from(inner: FormatErrorInner) -> Self {
443 FormatError { inner }
444 }
445}
446
447impl From<DecodingError> for io::Error {
448 fn from(err: DecodingError) -> io::Error {
449 match err {
450 DecodingError::IoError(err) => err,
451 err => io::Error::new(io::ErrorKind::Other, err.to_string()),
452 }
453 }
454}
455
456impl From<TextDecodingError> for DecodingError {
457 fn from(tbe: TextDecodingError) -> Self {
458 DecodingError::Format(FormatError {
459 inner: FormatErrorInner::BadTextEncoding(tbe),
460 })
461 }
462}
463
464#[derive(Clone)]
466pub struct DecodeOptions {
467 ignore_adler32: bool,
468 ignore_crc: bool,
469 ignore_text_chunk: bool,
470 ignore_iccp_chunk: bool,
471 skip_ancillary_crc_failures: bool,
472}
473
474impl Default for DecodeOptions {
475 fn default() -> Self {
476 Self {
477 ignore_adler32: true,
478 ignore_crc: false,
479 ignore_text_chunk: false,
480 ignore_iccp_chunk: false,
481 skip_ancillary_crc_failures: true,
482 }
483 }
484}
485
486impl DecodeOptions {
487 pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) {
491 self.ignore_adler32 = ignore_adler32;
492 }
493
494 pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
498 self.ignore_crc = ignore_crc;
499 }
500
501 pub fn set_ignore_checksums(&mut self, ignore_checksums: bool) {
504 self.ignore_adler32 = ignore_checksums;
505 self.ignore_crc = ignore_checksums;
506 }
507
508 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
512 self.ignore_text_chunk = ignore_text_chunk;
513 }
514
515 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
519 self.ignore_iccp_chunk = ignore_iccp_chunk;
520 }
521
522 pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
526 self.skip_ancillary_crc_failures = skip_ancillary_crc_failures;
527 }
528}
529
530pub struct StreamingDecoder {
536 state: Option<State>,
537 current_chunk: ChunkState,
538 inflater: ZlibStream,
540 pub(crate) info: Option<Info<'static>>,
542 current_seq_no: Option<u32>,
544 have_idat: bool,
547 ready_for_idat_chunks: bool,
550 ready_for_fdat_chunks: bool,
554 have_iccp: bool,
556 decode_options: DecodeOptions,
557 pub(crate) limits: Limits,
558}
559
560struct ChunkState {
561 type_: ChunkType,
564
565 crc: Crc32,
567
568 remaining: u32,
570
571 raw_bytes: Vec<u8>,
573}
574
575impl StreamingDecoder {
576 pub fn new() -> StreamingDecoder {
580 StreamingDecoder::new_with_options(DecodeOptions::default())
581 }
582
583 pub fn new_with_options(decode_options: DecodeOptions) -> StreamingDecoder {
584 let mut inflater = ZlibStream::new();
585 inflater.set_ignore_adler32(decode_options.ignore_adler32);
586
587 StreamingDecoder {
588 state: Some(State::new_u32(U32ValueKind::Signature1stU32)),
589 current_chunk: ChunkState {
590 type_: ChunkType([0; 4]),
591 crc: Crc32::new(),
592 remaining: 0,
593 raw_bytes: Vec::with_capacity(CHUNK_BUFFER_SIZE),
594 },
595 inflater,
596 info: None,
597 current_seq_no: None,
598 have_idat: false,
599 have_iccp: false,
600 ready_for_idat_chunks: true,
601 ready_for_fdat_chunks: false,
602 decode_options,
603 limits: Limits { bytes: usize::MAX },
604 }
605 }
606
607 pub fn reset(&mut self) {
609 self.state = Some(State::new_u32(U32ValueKind::Signature1stU32));
610 self.current_chunk.crc = Crc32::new();
611 self.current_chunk.remaining = 0;
612 self.current_chunk.raw_bytes.clear();
613 self.inflater.reset();
614 self.info = None;
615 self.current_seq_no = None;
616 self.have_idat = false;
617 }
618
619 pub fn info(&self) -> Option<&Info<'static>> {
621 self.info.as_ref()
622 }
623
624 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
625 self.decode_options.set_ignore_text_chunk(ignore_text_chunk);
626 }
627
628 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
629 self.decode_options.set_ignore_iccp_chunk(ignore_iccp_chunk);
630 }
631
632 pub fn ignore_adler32(&self) -> bool {
634 self.inflater.ignore_adler32()
635 }
636
637 pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) -> bool {
645 self.inflater.set_ignore_adler32(ignore_adler32)
646 }
647
648 pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
653 self.decode_options.set_ignore_crc(ignore_crc)
654 }
655
656 pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
660 self.decode_options
661 .set_skip_ancillary_crc_failures(skip_ancillary_crc_failures)
662 }
663
664 pub fn update(
670 &mut self,
671 mut buf: &[u8],
672 mut image_data: Option<&mut UnfilterBuf<'_>>,
673 ) -> Result<(usize, Decoded), DecodingError> {
674 if self.state.is_none() {
675 return Err(DecodingError::Parameter(
676 ParameterErrorKind::PolledAfterFatalError.into(),
677 ));
678 }
679
680 let len = buf.len();
681 while !buf.is_empty() {
682 let image_data = image_data.as_deref_mut();
683
684 match self.next_state(buf, image_data) {
685 Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..],
686 Ok((bytes, result)) => {
687 buf = &buf[bytes..];
688 return Ok((len - buf.len(), result));
689 }
690 Err(err) => {
691 debug_assert!(self.state.is_none());
692 return Err(err);
693 }
694 }
695 }
696 Ok((len - buf.len(), Decoded::Nothing))
697 }
698
699 fn next_state(
700 &mut self,
701 buf: &[u8],
702 image_data: Option<&mut UnfilterBuf<'_>>,
703 ) -> Result<(usize, Decoded), DecodingError> {
704 use self::State::*;
705
706 let state = self.state.take().unwrap();
708
709 match state {
710 U32 {
711 kind,
712 mut bytes,
713 mut accumulated_count,
714 } => {
715 debug_assert!(accumulated_count <= 4);
716 if accumulated_count == 0 && buf.len() >= 4 {
717 const CONSUMED_BYTES: usize = 4;
723 self.parse_u32(kind, &buf[0..4], image_data)
724 .map(|decoded| (CONSUMED_BYTES, decoded))
725 } else {
726 let remaining_count = 4 - accumulated_count;
727 let consumed_bytes = {
728 let available_count = min(remaining_count, buf.len());
729 bytes[accumulated_count..accumulated_count + available_count]
730 .copy_from_slice(&buf[0..available_count]);
731 accumulated_count += available_count;
732 available_count
733 };
734
735 if accumulated_count < 4 {
736 self.state = Some(U32 {
737 kind,
738 bytes,
739 accumulated_count,
740 });
741 Ok((consumed_bytes, Decoded::Nothing))
742 } else {
743 debug_assert_eq!(accumulated_count, 4);
744 self.parse_u32(kind, &bytes, image_data)
745 .map(|decoded| (consumed_bytes, decoded))
746 }
747 }
748 }
749 ReadChunkData(type_str) => {
750 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
751 if self.current_chunk.remaining == 0 {
752 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
753 Ok((0, Decoded::Nothing))
754 } else {
755 let ChunkState {
756 crc,
757 remaining,
758 raw_bytes,
759 type_: _,
760 } = &mut self.current_chunk;
761
762 if raw_bytes.len() == raw_bytes.capacity() {
763 if self.limits.bytes == 0 {
764 return Err(DecodingError::LimitsExceeded);
765 }
766
767 debug_assert!(raw_bytes.capacity() > 0);
769 let reserve_size = raw_bytes.capacity().min(self.limits.bytes);
770
771 self.limits.reserve_bytes(reserve_size)?;
772 raw_bytes.reserve_exact(reserve_size);
773 }
774
775 let buf_avail = raw_bytes.capacity() - raw_bytes.len();
776 let bytes_avail = min(buf.len(), buf_avail);
777 let n = min(*remaining, bytes_avail as u32);
778
779 let buf = &buf[..n as usize];
780 if !self.decode_options.ignore_crc {
781 crc.update(buf);
782 }
783 raw_bytes.extend_from_slice(buf);
784
785 *remaining -= n;
786 if *remaining == 0 {
787 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
788 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
789 } else {
790 self.state = Some(ReadChunkData(type_str));
791 }
792 Ok((n as usize, Decoded::Nothing))
793 }
794 }
795 ImageData(type_str) => {
796 debug_assert!(type_str == IDAT || type_str == chunk::fdAT);
797 let len = std::cmp::min(buf.len(), self.current_chunk.remaining as usize);
798 let buf = &buf[..len];
799
800 let consumed = if let Some(image_data) = image_data {
801 self.inflater.decompress(buf, image_data)?
802 } else {
803 len
804 };
805
806 if !self.decode_options.ignore_crc {
807 self.current_chunk.crc.update(&buf[..consumed]);
808 }
809
810 self.current_chunk.remaining -= consumed as u32;
811 if self.current_chunk.remaining == 0 {
812 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
813 } else {
814 self.state = Some(ImageData(type_str));
815 }
816 Ok((consumed, Decoded::ImageData))
817 }
818 }
819 }
820
821 fn parse_u32(
822 &mut self,
823 kind: U32ValueKind,
824 u32_be_bytes: &[u8],
825 image_data: Option<&mut UnfilterBuf<'_>>,
826 ) -> Result<Decoded, DecodingError> {
827 debug_assert_eq!(u32_be_bytes.len(), 4);
828 let bytes = u32_be_bytes.try_into().unwrap();
829 let val = u32::from_be_bytes(bytes);
830
831 match kind {
832 U32ValueKind::Signature1stU32 => {
833 if bytes == [137, 80, 78, 71] {
834 self.state = Some(State::new_u32(U32ValueKind::Signature2ndU32));
835 Ok(Decoded::Nothing)
836 } else {
837 Err(DecodingError::Format(
838 FormatErrorInner::InvalidSignature.into(),
839 ))
840 }
841 }
842 U32ValueKind::Signature2ndU32 => {
843 if bytes == [13, 10, 26, 10] {
844 self.state = Some(State::new_u32(U32ValueKind::Length));
845 Ok(Decoded::Nothing)
846 } else {
847 Err(DecodingError::Format(
848 FormatErrorInner::InvalidSignature.into(),
849 ))
850 }
851 }
852 U32ValueKind::Length => {
853 self.state = Some(State::new_u32(U32ValueKind::Type { length: val }));
854 Ok(Decoded::Nothing)
855 }
856 U32ValueKind::Type { length } => {
857 let type_str = ChunkType(bytes);
858 if self.info.is_none() && type_str != IHDR {
859 return Err(DecodingError::Format(
860 FormatErrorInner::ChunkBeforeIhdr { kind: type_str }.into(),
861 ));
862 }
863 if type_str != self.current_chunk.type_
864 && (self.current_chunk.type_ == IDAT || self.current_chunk.type_ == chunk::fdAT)
865 {
866 self.current_chunk.type_ = type_str;
867 if let Some(image_data) = image_data {
868 self.inflater.finish_compressed_chunks(image_data)?;
869 }
870
871 self.ready_for_idat_chunks = false;
872 self.ready_for_fdat_chunks = false;
873 self.state = Some(State::U32 {
874 kind,
875 bytes,
876 accumulated_count: 4,
877 });
878 return Ok(Decoded::ImageDataFlushed);
879 }
880 self.state = match type_str {
881 chunk::fdAT => {
882 if !self.ready_for_fdat_chunks {
883 return Err(DecodingError::Format(
884 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
885 kind: chunk::fdAT,
886 }
887 .into(),
888 ));
889 }
890 if length < 4 {
891 return Err(DecodingError::Format(
892 FormatErrorInner::FdatShorterThanFourBytes.into(),
893 ));
894 }
895 Some(State::new_u32(U32ValueKind::ApngSequenceNumber))
896 }
897 IDAT => {
898 if !self.ready_for_idat_chunks {
899 return Err(DecodingError::Format(
900 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
901 kind: IDAT,
902 }
903 .into(),
904 ));
905 }
906 self.have_idat = true;
907 Some(State::ImageData(type_str))
908 }
909 _ => Some(State::ReadChunkData(type_str)),
910 };
911 self.current_chunk.type_ = type_str;
912 if !self.decode_options.ignore_crc {
913 self.current_chunk.crc.reset();
914 self.current_chunk.crc.update(&type_str.0);
915 }
916 self.current_chunk.remaining = length;
917 self.current_chunk.raw_bytes.clear();
918 Ok(Decoded::ChunkBegin(length, type_str))
919 }
920 U32ValueKind::Crc(type_str) => {
921 let sum = if self.decode_options.ignore_crc {
925 val
926 } else {
927 self.current_chunk.crc.clone().finalize()
928 };
929
930 if val == sum || CHECKSUM_DISABLED {
931 debug_assert!(self.state.is_none());
934 let decoded = self.parse_chunk(type_str)?;
935
936 if type_str != IEND {
937 self.state = Some(State::new_u32(U32ValueKind::Length));
938 }
939 Ok(decoded)
940 } else if self.decode_options.skip_ancillary_crc_failures
941 && !chunk::is_critical(type_str)
942 {
943 self.state = Some(State::new_u32(U32ValueKind::Length));
945 Ok(Decoded::BadAncillaryChunk(type_str))
946 } else {
947 Err(DecodingError::Format(
948 FormatErrorInner::CrcMismatch {
949 crc_val: val,
950 crc_sum: sum,
951 chunk: type_str,
952 }
953 .into(),
954 ))
955 }
956 }
957 U32ValueKind::ApngSequenceNumber => {
958 debug_assert_eq!(self.current_chunk.type_, chunk::fdAT);
959 let next_seq_no = val;
960
961 debug_assert!(self.current_chunk.remaining >= 4);
963 self.current_chunk.remaining -= 4;
964
965 if let Some(seq_no) = self.current_seq_no {
966 if next_seq_no != seq_no + 1 {
967 return Err(DecodingError::Format(
968 FormatErrorInner::ApngOrder {
969 present: next_seq_no,
970 expected: seq_no + 1,
971 }
972 .into(),
973 ));
974 }
975 self.current_seq_no = Some(next_seq_no);
976 } else {
977 return Err(DecodingError::Format(FormatErrorInner::MissingFctl.into()));
978 }
979
980 if !self.decode_options.ignore_crc {
981 let data = next_seq_no.to_be_bytes();
982 self.current_chunk.crc.update(&data);
983 }
984
985 self.state = Some(State::ImageData(chunk::fdAT));
986 Ok(Decoded::Nothing)
987 }
988 }
989 }
990
991 fn parse_chunk(&mut self, type_str: ChunkType) -> Result<Decoded, DecodingError> {
992 let mut parse_result = match type_str {
993 IHDR => self.parse_ihdr(),
995 chunk::PLTE => self.parse_plte(),
996 chunk::IEND => Ok(()), chunk::IDAT => Ok(()),
1000 chunk::fdAT => Ok(()),
1001
1002 chunk::sBIT => self.parse_sbit(),
1004 chunk::tRNS => self.parse_trns(),
1005 chunk::pHYs => self.parse_phys(),
1006 chunk::gAMA => self.parse_gama(),
1007 chunk::acTL => self.parse_actl(),
1008 chunk::fcTL => self.parse_fctl(),
1009 chunk::cHRM => self.parse_chrm(),
1010 chunk::sRGB => self.parse_srgb(),
1011 chunk::cICP => self.parse_cicp(),
1012 chunk::mDCV => self.parse_mdcv(),
1013 chunk::cLLI => self.parse_clli(),
1014 chunk::bKGD => self.parse_bkgd(),
1015
1016 chunk::eXIf => self.parse_exif(), chunk::iCCP if !self.decode_options.ignore_iccp_chunk => self.parse_iccp(),
1019 chunk::tEXt if !self.decode_options.ignore_text_chunk => self.parse_text(),
1020 chunk::zTXt if !self.decode_options.ignore_text_chunk => self.parse_ztxt(),
1021 chunk::iTXt if !self.decode_options.ignore_text_chunk => self.parse_itxt(),
1022
1023 _ => {
1025 if is_critical(type_str) {
1026 return Err(DecodingError::Format(
1027 FormatErrorInner::UnrecognizedCriticalChunk { type_str }.into(),
1028 ));
1029 } else {
1030 return Ok(Decoded::SkippedAncillaryChunk(type_str));
1031 }
1032 }
1033 };
1034
1035 parse_result = parse_result.map_err(|e| {
1036 match e {
1037 DecodingError::IoError(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
1042 let fmt_err: FormatError =
1043 FormatErrorInner::ChunkTooShort { kind: type_str }.into();
1044 fmt_err.into()
1045 }
1046 e => e,
1047 }
1048 });
1049
1050 match parse_result {
1051 Ok(()) => Ok(Decoded::ChunkComplete(type_str)),
1052 Err(DecodingError::Format(_))
1053 if type_str != chunk::fcTL && !chunk::is_critical(type_str) =>
1054 {
1055 Ok(Decoded::BadAncillaryChunk(type_str))
1063 }
1064 Err(e) => Err(e),
1065 }
1066 }
1067
1068 fn parse_fctl(&mut self) -> Result<(), DecodingError> {
1069 let mut buf = &self.current_chunk.raw_bytes[..];
1070 let next_seq_no = buf.read_be()?;
1071
1072 self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
1074 if next_seq_no != seq_no + 1 {
1075 return Err(DecodingError::Format(
1076 FormatErrorInner::ApngOrder {
1077 expected: seq_no + 1,
1078 present: next_seq_no,
1079 }
1080 .into(),
1081 ));
1082 }
1083 next_seq_no
1084 } else {
1085 if next_seq_no != 0 {
1086 return Err(DecodingError::Format(
1087 FormatErrorInner::ApngOrder {
1088 expected: 0,
1089 present: next_seq_no,
1090 }
1091 .into(),
1092 ));
1093 }
1094 0
1095 });
1096 self.inflater.reset();
1097 self.ready_for_fdat_chunks = true;
1098 let fc = FrameControl {
1099 sequence_number: next_seq_no,
1100 width: buf.read_be()?,
1101 height: buf.read_be()?,
1102 x_offset: buf.read_be()?,
1103 y_offset: buf.read_be()?,
1104 delay_num: buf.read_be()?,
1105 delay_den: buf.read_be()?,
1106 dispose_op: {
1107 let dispose_op = buf.read_be()?;
1108 match DisposeOp::from_u8(dispose_op) {
1109 Some(dispose_op) => dispose_op,
1110 None => {
1111 return Err(DecodingError::Format(
1112 FormatErrorInner::InvalidDisposeOp(dispose_op).into(),
1113 ))
1114 }
1115 }
1116 },
1117 blend_op: {
1118 let blend_op = buf.read_be()?;
1119 match BlendOp::from_u8(blend_op) {
1120 Some(blend_op) => blend_op,
1121 None => {
1122 return Err(DecodingError::Format(
1123 FormatErrorInner::InvalidBlendOp(blend_op).into(),
1124 ))
1125 }
1126 }
1127 },
1128 };
1129 self.info.as_ref().unwrap().validate(&fc)?;
1130 if !self.have_idat {
1131 self.info.as_ref().unwrap().validate_default_image(&fc)?;
1132 }
1133 self.info.as_mut().unwrap().frame_control = Some(fc);
1134 Ok(())
1135 }
1136
1137 fn parse_actl(&mut self) -> Result<(), DecodingError> {
1138 if self.have_idat {
1139 Err(DecodingError::Format(
1140 FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1141 ))
1142 } else {
1143 let mut buf = &self.current_chunk.raw_bytes[..];
1144 let actl = AnimationControl {
1145 num_frames: buf.read_be()?,
1146 num_plays: buf.read_be()?,
1147 };
1148 if actl.num_frames == 0 {
1151 return Ok(());
1152 }
1153 self.info.as_mut().unwrap().animation_control = Some(actl);
1154 Ok(())
1155 }
1156 }
1157
1158 fn parse_plte(&mut self) -> Result<(), DecodingError> {
1159 let info = self.info.as_mut().unwrap();
1160 if info.palette.is_some() {
1161 Err(DecodingError::Format(
1163 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1164 ))
1165 } else {
1166 self.limits
1167 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1168 info.palette = Some(Cow::Owned(self.current_chunk.raw_bytes.clone()));
1169 Ok(())
1170 }
1171 }
1172
1173 fn parse_sbit(&mut self) -> Result<(), DecodingError> {
1174 let info = self.info.as_mut().unwrap();
1175 if info.palette.is_some() {
1176 return Err(DecodingError::Format(
1177 FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
1178 ));
1179 }
1180
1181 if self.have_idat {
1182 return Err(DecodingError::Format(
1183 FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
1184 ));
1185 }
1186
1187 if info.sbit.is_some() {
1188 return Err(DecodingError::Format(
1189 FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
1190 ));
1191 }
1192
1193 let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
1194 let sample_depth = if color_type == ColorType::Indexed {
1196 BitDepth::Eight
1197 } else {
1198 bit_depth
1199 };
1200 self.limits
1201 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1202 let vec = self.current_chunk.raw_bytes.clone();
1203 let len = vec.len();
1204
1205 let expected = match color_type {
1207 ColorType::Grayscale => 1,
1208 ColorType::Rgb | ColorType::Indexed => 3,
1209 ColorType::GrayscaleAlpha => 2,
1210 ColorType::Rgba => 4,
1211 };
1212
1213 if expected != len {
1215 return Err(DecodingError::Format(
1216 FormatErrorInner::InvalidSbitChunkSize {
1217 color_type,
1218 expected,
1219 len,
1220 }
1221 .into(),
1222 ));
1223 }
1224
1225 for sbit in &vec {
1226 if *sbit < 1 || *sbit > sample_depth as u8 {
1227 return Err(DecodingError::Format(
1228 FormatErrorInner::InvalidSbit {
1229 sample_depth,
1230 sbit: *sbit,
1231 }
1232 .into(),
1233 ));
1234 }
1235 }
1236 info.sbit = Some(Cow::Owned(vec));
1237 Ok(())
1238 }
1239
1240 fn parse_trns(&mut self) -> Result<(), DecodingError> {
1241 let info = self.info.as_mut().unwrap();
1242 if info.trns.is_some() {
1243 return Err(DecodingError::Format(
1244 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1245 ));
1246 }
1247 let (color_type, bit_depth) = { (info.color_type, info.bit_depth as u8) };
1248 self.limits
1249 .reserve_bytes(self.current_chunk.raw_bytes.len())?;
1250 let mut vec = self.current_chunk.raw_bytes.clone();
1251 let len = vec.len();
1252 match color_type {
1253 ColorType::Grayscale => {
1254 if len < 2 {
1255 return Err(DecodingError::Format(
1256 FormatErrorInner::ShortPalette { expected: 2, len }.into(),
1257 ));
1258 }
1259 if bit_depth < 16 {
1260 vec[0] = vec[1];
1261 vec.truncate(1);
1262 }
1263 info.trns = Some(Cow::Owned(vec));
1264 Ok(())
1265 }
1266 ColorType::Rgb => {
1267 if len < 6 {
1268 return Err(DecodingError::Format(
1269 FormatErrorInner::ShortPalette { expected: 6, len }.into(),
1270 ));
1271 }
1272 if bit_depth < 16 {
1273 vec[0] = vec[1];
1274 vec[1] = vec[3];
1275 vec[2] = vec[5];
1276 vec.truncate(3);
1277 }
1278 info.trns = Some(Cow::Owned(vec));
1279 Ok(())
1280 }
1281 ColorType::Indexed => {
1282 if info.palette.is_none() {
1285 return Err(DecodingError::Format(
1286 FormatErrorInner::BeforePlte { kind: chunk::tRNS }.into(),
1287 ));
1288 } else if self.have_idat {
1289 return Err(DecodingError::Format(
1290 FormatErrorInner::OutsidePlteIdat { kind: chunk::tRNS }.into(),
1291 ));
1292 }
1293
1294 info.trns = Some(Cow::Owned(vec));
1295 Ok(())
1296 }
1297 c => Err(DecodingError::Format(
1298 FormatErrorInner::ColorWithBadTrns(c).into(),
1299 )),
1300 }
1301 }
1302
1303 fn parse_phys(&mut self) -> Result<(), DecodingError> {
1304 let info = self.info.as_mut().unwrap();
1305 if self.have_idat {
1306 Err(DecodingError::Format(
1307 FormatErrorInner::AfterIdat { kind: chunk::pHYs }.into(),
1308 ))
1309 } else if info.pixel_dims.is_some() {
1310 Err(DecodingError::Format(
1311 FormatErrorInner::DuplicateChunk { kind: chunk::pHYs }.into(),
1312 ))
1313 } else {
1314 let mut buf = &self.current_chunk.raw_bytes[..];
1315 let xppu = buf.read_be()?;
1316 let yppu = buf.read_be()?;
1317 let unit = buf.read_be()?;
1318 let unit = match Unit::from_u8(unit) {
1319 Some(unit) => unit,
1320 None => {
1321 return Err(DecodingError::Format(
1322 FormatErrorInner::InvalidUnit(unit).into(),
1323 ))
1324 }
1325 };
1326 let pixel_dims = PixelDimensions { xppu, yppu, unit };
1327 info.pixel_dims = Some(pixel_dims);
1328 Ok(())
1329 }
1330 }
1331
1332 fn parse_chrm(&mut self) -> Result<(), DecodingError> {
1333 let info = self.info.as_mut().unwrap();
1334 if self.have_idat {
1335 Err(DecodingError::Format(
1336 FormatErrorInner::AfterIdat { kind: chunk::cHRM }.into(),
1337 ))
1338 } else if info.chrm_chunk.is_some() {
1339 Err(DecodingError::Format(
1340 FormatErrorInner::DuplicateChunk { kind: chunk::cHRM }.into(),
1341 ))
1342 } else {
1343 let mut buf = &self.current_chunk.raw_bytes[..];
1344 let white_x: u32 = buf.read_be()?;
1345 let white_y: u32 = buf.read_be()?;
1346 let red_x: u32 = buf.read_be()?;
1347 let red_y: u32 = buf.read_be()?;
1348 let green_x: u32 = buf.read_be()?;
1349 let green_y: u32 = buf.read_be()?;
1350 let blue_x: u32 = buf.read_be()?;
1351 let blue_y: u32 = buf.read_be()?;
1352
1353 let source_chromaticities = SourceChromaticities {
1354 white: (
1355 ScaledFloat::from_scaled(white_x),
1356 ScaledFloat::from_scaled(white_y),
1357 ),
1358 red: (
1359 ScaledFloat::from_scaled(red_x),
1360 ScaledFloat::from_scaled(red_y),
1361 ),
1362 green: (
1363 ScaledFloat::from_scaled(green_x),
1364 ScaledFloat::from_scaled(green_y),
1365 ),
1366 blue: (
1367 ScaledFloat::from_scaled(blue_x),
1368 ScaledFloat::from_scaled(blue_y),
1369 ),
1370 };
1371
1372 info.chrm_chunk = Some(source_chromaticities);
1373 Ok(())
1374 }
1375 }
1376
1377 fn parse_gama(&mut self) -> Result<(), DecodingError> {
1378 let info = self.info.as_mut().unwrap();
1379 if self.have_idat {
1380 Err(DecodingError::Format(
1381 FormatErrorInner::AfterIdat { kind: chunk::gAMA }.into(),
1382 ))
1383 } else if info.gama_chunk.is_some() {
1384 Err(DecodingError::Format(
1385 FormatErrorInner::DuplicateChunk { kind: chunk::gAMA }.into(),
1386 ))
1387 } else {
1388 let mut buf = &self.current_chunk.raw_bytes[..];
1389 let source_gamma: u32 = buf.read_be()?;
1390 if source_gamma == 0 {
1391 return Err(DecodingError::Format(
1392 FormatErrorInner::BadGammaValue.into(),
1393 ));
1394 }
1395
1396 let source_gamma = ScaledFloat::from_scaled(source_gamma);
1397 info.gama_chunk = Some(source_gamma);
1398 Ok(())
1399 }
1400 }
1401
1402 fn parse_srgb(&mut self) -> Result<(), DecodingError> {
1403 let info = self.info.as_mut().unwrap();
1404 if self.have_idat {
1405 Err(DecodingError::Format(
1406 FormatErrorInner::AfterIdat { kind: chunk::sRGB }.into(),
1407 ))
1408 } else if info.srgb.is_some() {
1409 Err(DecodingError::Format(
1410 FormatErrorInner::DuplicateChunk { kind: chunk::sRGB }.into(),
1411 ))
1412 } else {
1413 let mut buf = &self.current_chunk.raw_bytes[..];
1414 let raw: u8 = buf.read_be()?; let rendering_intent = crate::SrgbRenderingIntent::from_raw(raw).ok_or_else(|| {
1416 FormatError::from(FormatErrorInner::InvalidSrgbRenderingIntent(raw))
1417 })?;
1418
1419 info.srgb = Some(rendering_intent);
1421 Ok(())
1422 }
1423 }
1424
1425 fn parse_cicp(&mut self) -> Result<(), DecodingError> {
1426 let info = self.info.as_mut().unwrap();
1427
1428 if info.coding_independent_code_points.is_some() {
1430 return Err(DecodingError::Format(
1431 FormatErrorInner::DuplicateChunk { kind: chunk::cICP }.into(),
1432 ));
1433 } else if info.palette.is_some() {
1434 return Err(DecodingError::Format(
1435 FormatErrorInner::AfterPlte { kind: chunk::cICP }.into(),
1436 ));
1437 } else if self.have_idat {
1438 return Err(DecodingError::Format(
1439 FormatErrorInner::AfterIdat { kind: chunk::cICP }.into(),
1440 ));
1441 }
1442
1443 let mut buf = &*self.current_chunk.raw_bytes;
1444 let color_primaries: u8 = buf.read_be()?;
1445 let transfer_function: u8 = buf.read_be()?;
1446 let matrix_coefficients: u8 = buf.read_be()?;
1447 let is_video_full_range_image = {
1448 let flag: u8 = buf.read_be()?;
1449 match flag {
1450 0 => false,
1451 1 => true,
1452 _ => {
1453 return Err(DecodingError::IoError(
1454 std::io::ErrorKind::InvalidData.into(),
1455 ));
1456 }
1457 }
1458 };
1459
1460 if matrix_coefficients != 0 {
1463 return Err(DecodingError::IoError(
1464 std::io::ErrorKind::InvalidData.into(),
1465 ));
1466 }
1467
1468 if !buf.is_empty() {
1469 return Err(DecodingError::IoError(
1470 std::io::ErrorKind::InvalidData.into(),
1471 ));
1472 }
1473
1474 info.coding_independent_code_points = Some(CodingIndependentCodePoints {
1475 color_primaries,
1476 transfer_function,
1477 matrix_coefficients,
1478 is_video_full_range_image,
1479 });
1480
1481 Ok(())
1482 }
1483
1484 fn parse_mdcv(&mut self) -> Result<(), DecodingError> {
1485 let info = self.info.as_mut().unwrap();
1486
1487 if info.mastering_display_color_volume.is_some() {
1489 return Err(DecodingError::Format(
1490 FormatErrorInner::DuplicateChunk { kind: chunk::mDCV }.into(),
1491 ));
1492 } else if info.palette.is_some() {
1493 return Err(DecodingError::Format(
1494 FormatErrorInner::AfterPlte { kind: chunk::mDCV }.into(),
1495 ));
1496 } else if self.have_idat {
1497 return Err(DecodingError::Format(
1498 FormatErrorInner::AfterIdat { kind: chunk::mDCV }.into(),
1499 ));
1500 }
1501
1502 let mut buf = &*self.current_chunk.raw_bytes;
1503 let red_x: u16 = buf.read_be()?;
1504 let red_y: u16 = buf.read_be()?;
1505 let green_x: u16 = buf.read_be()?;
1506 let green_y: u16 = buf.read_be()?;
1507 let blue_x: u16 = buf.read_be()?;
1508 let blue_y: u16 = buf.read_be()?;
1509 let white_x: u16 = buf.read_be()?;
1510 let white_y: u16 = buf.read_be()?;
1511 fn scale(chunk: u16) -> ScaledFloat {
1512 ScaledFloat::from_scaled((chunk as u32) * 2)
1519 }
1520 let chromaticities = SourceChromaticities {
1521 white: (scale(white_x), scale(white_y)),
1522 red: (scale(red_x), scale(red_y)),
1523 green: (scale(green_x), scale(green_y)),
1524 blue: (scale(blue_x), scale(blue_y)),
1525 };
1526 let max_luminance: u32 = buf.read_be()?;
1527 let min_luminance: u32 = buf.read_be()?;
1528 if !buf.is_empty() {
1529 return Err(DecodingError::IoError(
1530 std::io::ErrorKind::InvalidData.into(),
1531 ));
1532 }
1533 info.mastering_display_color_volume = Some(MasteringDisplayColorVolume {
1534 chromaticities,
1535 max_luminance,
1536 min_luminance,
1537 });
1538
1539 Ok(())
1540 }
1541
1542 fn parse_clli(&mut self) -> Result<(), DecodingError> {
1543 let info = self.info.as_mut().unwrap();
1544 if info.content_light_level.is_some() {
1545 return Err(DecodingError::Format(
1546 FormatErrorInner::DuplicateChunk { kind: chunk::cLLI }.into(),
1547 ));
1548 }
1549
1550 let mut buf = &*self.current_chunk.raw_bytes;
1551 let max_content_light_level: u32 = buf.read_be()?;
1552 let max_frame_average_light_level: u32 = buf.read_be()?;
1553 if !buf.is_empty() {
1554 return Err(DecodingError::IoError(
1555 std::io::ErrorKind::InvalidData.into(),
1556 ));
1557 }
1558 info.content_light_level = Some(ContentLightLevelInfo {
1559 max_content_light_level,
1560 max_frame_average_light_level,
1561 });
1562
1563 Ok(())
1564 }
1565
1566 fn parse_exif(&mut self) -> Result<(), DecodingError> {
1567 let info = self.info.as_mut().unwrap();
1568 if info.exif_metadata.is_some() {
1569 return Err(DecodingError::Format(
1570 FormatErrorInner::DuplicateChunk { kind: chunk::eXIf }.into(),
1571 ));
1572 }
1573
1574 info.exif_metadata = Some(self.current_chunk.raw_bytes.clone().into());
1575 Ok(())
1576 }
1577
1578 fn parse_iccp(&mut self) -> Result<(), DecodingError> {
1579 if self.have_idat {
1580 Err(DecodingError::Format(
1581 FormatErrorInner::AfterIdat { kind: chunk::iCCP }.into(),
1582 ))
1583 } else if self.have_iccp {
1584 Err(DecodingError::Format(
1585 FormatErrorInner::DuplicateChunk { kind: chunk::iCCP }.into(),
1586 ))
1587 } else {
1588 self.have_iccp = true;
1589 let _ = self.parse_iccp_raw();
1590 Ok(())
1591 }
1592 }
1593
1594 fn parse_iccp_raw(&mut self) -> Result<(), DecodingError> {
1595 let info = self.info.as_mut().unwrap();
1596 let mut buf = &self.current_chunk.raw_bytes[..];
1597
1598 for len in 0..=80 {
1600 let raw: u8 = buf.read_be()?;
1601 if (raw == 0 && len == 0) || (raw != 0 && len == 80) {
1602 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1603 }
1604 if raw == 0 {
1605 break;
1606 }
1607 }
1608
1609 match buf.read_be()? {
1610 0u8 => (),
1612 n => {
1613 return Err(DecodingError::Format(
1614 FormatErrorInner::UnknownCompressionMethod(n).into(),
1615 ))
1616 }
1617 }
1618
1619 match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) {
1620 Ok(profile) => {
1621 self.limits.reserve_bytes(profile.len())?;
1622 info.icc_profile = Some(Cow::Owned(profile));
1623 }
1624 Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => {
1625 return Err(DecodingError::Format(
1626 FormatErrorInner::CorruptFlateStream { err }.into(),
1627 ))
1628 }
1629 Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => {
1630 return Err(DecodingError::LimitsExceeded);
1631 }
1632 }
1633
1634 Ok(())
1635 }
1636
1637 fn parse_ihdr(&mut self) -> Result<(), DecodingError> {
1638 if self.info.is_some() {
1639 return Err(DecodingError::Format(
1640 FormatErrorInner::DuplicateChunk { kind: IHDR }.into(),
1641 ));
1642 }
1643 let mut buf = &self.current_chunk.raw_bytes[..];
1644 let width = buf.read_be()?;
1645 let height = buf.read_be()?;
1646 if width == 0 || height == 0 {
1647 return Err(DecodingError::Format(
1648 FormatErrorInner::InvalidDimensions.into(),
1649 ));
1650 }
1651 let bit_depth = buf.read_be()?;
1652 let bit_depth = match BitDepth::from_u8(bit_depth) {
1653 Some(bits) => bits,
1654 None => {
1655 return Err(DecodingError::Format(
1656 FormatErrorInner::InvalidBitDepth(bit_depth).into(),
1657 ))
1658 }
1659 };
1660 let color_type = buf.read_be()?;
1661 let color_type = match ColorType::from_u8(color_type) {
1662 Some(color_type) => {
1663 if color_type.is_combination_invalid(bit_depth) {
1664 return Err(DecodingError::Format(
1665 FormatErrorInner::InvalidColorBitDepth {
1666 color_type,
1667 bit_depth,
1668 }
1669 .into(),
1670 ));
1671 } else {
1672 color_type
1673 }
1674 }
1675 None => {
1676 return Err(DecodingError::Format(
1677 FormatErrorInner::InvalidColorType(color_type).into(),
1678 ))
1679 }
1680 };
1681 match buf.read_be()? {
1682 0u8 => (),
1684 n => {
1685 return Err(DecodingError::Format(
1686 FormatErrorInner::UnknownCompressionMethod(n).into(),
1687 ))
1688 }
1689 }
1690 match buf.read_be()? {
1691 0u8 => (),
1693 n => {
1694 return Err(DecodingError::Format(
1695 FormatErrorInner::UnknownFilterMethod(n).into(),
1696 ))
1697 }
1698 }
1699 let interlaced = match buf.read_be()? {
1700 0u8 => false,
1701 1 => true,
1702 n => {
1703 return Err(DecodingError::Format(
1704 FormatErrorInner::UnknownInterlaceMethod(n).into(),
1705 ))
1706 }
1707 };
1708
1709 self.info = Some(Info {
1710 width,
1711 height,
1712 bit_depth,
1713 color_type,
1714 interlaced,
1715 ..Default::default()
1716 });
1717
1718 Ok(())
1719 }
1720
1721 fn split_keyword(buf: &[u8]) -> Result<(&[u8], &[u8]), DecodingError> {
1722 let null_byte_index = buf
1723 .iter()
1724 .position(|&b| b == 0)
1725 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?;
1726
1727 if null_byte_index == 0 || null_byte_index > 79 {
1728 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1729 }
1730
1731 Ok((&buf[..null_byte_index], &buf[null_byte_index + 1..]))
1732 }
1733
1734 fn parse_text(&mut self) -> Result<(), DecodingError> {
1735 let buf = &self.current_chunk.raw_bytes[..];
1736 self.limits.reserve_bytes(buf.len())?;
1737
1738 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1739
1740 self.info
1741 .as_mut()
1742 .unwrap()
1743 .uncompressed_latin1_text
1744 .push(TEXtChunk::decode(keyword_slice, value_slice).map_err(DecodingError::from)?);
1745
1746 Ok(())
1747 }
1748
1749 fn parse_ztxt(&mut self) -> Result<(), DecodingError> {
1750 let buf = &self.current_chunk.raw_bytes[..];
1751 self.limits.reserve_bytes(buf.len())?;
1752
1753 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1754
1755 let compression_method = *value_slice
1756 .first()
1757 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1758
1759 let text_slice = &value_slice[1..];
1760
1761 self.info.as_mut().unwrap().compressed_latin1_text.push(
1762 ZTXtChunk::decode(keyword_slice, compression_method, text_slice)
1763 .map_err(DecodingError::from)?,
1764 );
1765
1766 Ok(())
1767 }
1768
1769 fn parse_itxt(&mut self) -> Result<(), DecodingError> {
1770 let buf = &self.current_chunk.raw_bytes[..];
1771 self.limits.reserve_bytes(buf.len())?;
1772
1773 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1774
1775 let compression_flag = *value_slice
1776 .first()
1777 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingCompressionFlag))?;
1778
1779 let compression_method = *value_slice
1780 .get(1)
1781 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1782
1783 let second_null_byte_index = value_slice[2..]
1784 .iter()
1785 .position(|&b| b == 0)
1786 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1787 + 2;
1788
1789 let language_tag_slice = &value_slice[2..second_null_byte_index];
1790
1791 let third_null_byte_index = value_slice[second_null_byte_index + 1..]
1792 .iter()
1793 .position(|&b| b == 0)
1794 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1795 + (second_null_byte_index + 1);
1796
1797 let translated_keyword_slice =
1798 &value_slice[second_null_byte_index + 1..third_null_byte_index];
1799
1800 let text_slice = &value_slice[third_null_byte_index + 1..];
1801
1802 self.info.as_mut().unwrap().utf8_text.push(
1803 ITXtChunk::decode(
1804 keyword_slice,
1805 compression_flag,
1806 compression_method,
1807 language_tag_slice,
1808 translated_keyword_slice,
1809 text_slice,
1810 )
1811 .map_err(DecodingError::from)?,
1812 );
1813
1814 Ok(())
1815 }
1816
1817 fn parse_bkgd(&mut self) -> Result<(), DecodingError> {
1818 let info = self.info.as_mut().unwrap();
1819 if info.bkgd.is_some() {
1820 return Err(DecodingError::Format(
1822 FormatErrorInner::DuplicateChunk { kind: chunk::bKGD }.into(),
1823 ));
1824 } else if self.have_idat {
1825 return Err(DecodingError::Format(
1826 FormatErrorInner::AfterIdat { kind: chunk::bKGD }.into(),
1827 ));
1828 }
1829
1830 let expected = match info.color_type {
1831 ColorType::Indexed => {
1832 if info.palette.is_none() {
1833 return Err(DecodingError::IoError(
1834 std::io::ErrorKind::InvalidData.into(),
1835 ));
1836 };
1837 1
1838 }
1839 ColorType::Grayscale | ColorType::GrayscaleAlpha => 2,
1840 ColorType::Rgb | ColorType::Rgba => 6,
1841 };
1842 let vec = self.current_chunk.raw_bytes.clone();
1843 if vec.len() != expected {
1844 return Err(DecodingError::Format(
1845 FormatErrorInner::ChunkTooShort { kind: chunk::bKGD }.into(),
1846 ));
1847 }
1848
1849 info.bkgd = Some(Cow::Owned(vec));
1850 Ok(())
1851 }
1852}
1853
1854impl Info<'_> {
1855 fn validate_default_image(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1856 if fc.x_offset != 0
1865 || fc.y_offset != 0
1866 || fc.width != self.width
1867 || fc.height != self.height
1868 {
1869 return Err(DecodingError::Format(
1870 FormatErrorInner::BadSubFrameBounds {}.into(),
1871 ));
1872 }
1873 Ok(())
1874 }
1875
1876 fn validate(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1877 if fc.width == 0 || fc.height == 0 {
1878 return Err(DecodingError::Format(
1879 FormatErrorInner::InvalidDimensions.into(),
1880 ));
1881 }
1882
1883 let in_x_bounds = Some(fc.width) <= self.width.checked_sub(fc.x_offset);
1885 let in_y_bounds = Some(fc.height) <= self.height.checked_sub(fc.y_offset);
1887
1888 if !in_x_bounds || !in_y_bounds {
1889 return Err(DecodingError::Format(
1890 FormatErrorInner::BadSubFrameBounds {}.into(),
1892 ));
1893 }
1894
1895 Ok(())
1896 }
1897}
1898
1899impl Default for StreamingDecoder {
1900 fn default() -> Self {
1901 Self::new()
1902 }
1903}
1904
1905#[cfg(test)]
1906mod tests {
1907 use super::ScaledFloat;
1908 use super::SourceChromaticities;
1909 use crate::test_utils::*;
1910 use crate::{Decoder, DecodingError, Reader, SrgbRenderingIntent, Unit};
1911 use approx::assert_relative_eq;
1912 use byteorder::WriteBytesExt;
1913 use std::borrow::Cow;
1914 use std::cell::RefCell;
1915
1916 use std::fs::File;
1917 use std::io::BufRead;
1918 use std::io::Cursor;
1919 use std::io::Seek;
1920 use std::io::{BufReader, ErrorKind, Read, Write};
1921 use std::rc::Rc;
1922
1923 #[test]
1924 fn image_gamma() -> Result<(), ()> {
1925 fn trial(path: &str, expected: Option<ScaledFloat>) {
1926 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
1927 let reader = decoder.read_info().unwrap();
1928 let actual: Option<ScaledFloat> = reader.info().gamma();
1929 assert!(actual == expected);
1930 }
1931 trial("tests/pngsuite/f00n0g08.png", None);
1932 trial("tests/pngsuite/f00n2c08.png", None);
1933 trial("tests/pngsuite/f01n0g08.png", None);
1934 trial("tests/pngsuite/f01n2c08.png", None);
1935 trial("tests/pngsuite/f02n0g08.png", None);
1936 trial("tests/pngsuite/f02n2c08.png", None);
1937 trial("tests/pngsuite/f03n0g08.png", None);
1938 trial("tests/pngsuite/f03n2c08.png", None);
1939 trial("tests/pngsuite/f04n0g08.png", None);
1940 trial("tests/pngsuite/f04n2c08.png", None);
1941 trial("tests/pngsuite/f99n0g04.png", None);
1942 trial("tests/pngsuite/tm3n3p02.png", None);
1943 trial("tests/pngsuite/g03n0g16.png", Some(ScaledFloat::new(0.35)));
1944 trial("tests/pngsuite/g03n2c08.png", Some(ScaledFloat::new(0.35)));
1945 trial("tests/pngsuite/g03n3p04.png", Some(ScaledFloat::new(0.35)));
1946 trial("tests/pngsuite/g04n0g16.png", Some(ScaledFloat::new(0.45)));
1947 trial("tests/pngsuite/g04n2c08.png", Some(ScaledFloat::new(0.45)));
1948 trial("tests/pngsuite/g04n3p04.png", Some(ScaledFloat::new(0.45)));
1949 trial("tests/pngsuite/g05n0g16.png", Some(ScaledFloat::new(0.55)));
1950 trial("tests/pngsuite/g05n2c08.png", Some(ScaledFloat::new(0.55)));
1951 trial("tests/pngsuite/g05n3p04.png", Some(ScaledFloat::new(0.55)));
1952 trial("tests/pngsuite/g07n0g16.png", Some(ScaledFloat::new(0.7)));
1953 trial("tests/pngsuite/g07n2c08.png", Some(ScaledFloat::new(0.7)));
1954 trial("tests/pngsuite/g07n3p04.png", Some(ScaledFloat::new(0.7)));
1955 trial("tests/pngsuite/g10n0g16.png", Some(ScaledFloat::new(1.0)));
1956 trial("tests/pngsuite/g10n2c08.png", Some(ScaledFloat::new(1.0)));
1957 trial("tests/pngsuite/g10n3p04.png", Some(ScaledFloat::new(1.0)));
1958 trial("tests/pngsuite/g25n0g16.png", Some(ScaledFloat::new(2.5)));
1959 trial("tests/pngsuite/g25n2c08.png", Some(ScaledFloat::new(2.5)));
1960 trial("tests/pngsuite/g25n3p04.png", Some(ScaledFloat::new(2.5)));
1961 Ok(())
1962 }
1963
1964 #[test]
1965 fn image_source_chromaticities() -> Result<(), ()> {
1966 fn trial(path: &str, expected: Option<SourceChromaticities>) {
1967 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
1968 let reader = decoder.read_info().unwrap();
1969 let actual: Option<SourceChromaticities> = reader.info().chromaticities();
1970 assert!(actual == expected);
1971 }
1972 trial(
1973 "tests/pngsuite/ccwn2c08.png",
1974 Some(SourceChromaticities::new(
1975 (0.3127, 0.3290),
1976 (0.64, 0.33),
1977 (0.30, 0.60),
1978 (0.15, 0.06),
1979 )),
1980 );
1981 trial(
1982 "tests/pngsuite/ccwn3p08.png",
1983 Some(SourceChromaticities::new(
1984 (0.3127, 0.3290),
1985 (0.64, 0.33),
1986 (0.30, 0.60),
1987 (0.15, 0.06),
1988 )),
1989 );
1990 trial("tests/pngsuite/basi0g01.png", None);
1991 trial("tests/pngsuite/basi0g02.png", None);
1992 trial("tests/pngsuite/basi0g04.png", None);
1993 trial("tests/pngsuite/basi0g08.png", None);
1994 trial("tests/pngsuite/basi0g16.png", None);
1995 trial("tests/pngsuite/basi2c08.png", None);
1996 trial("tests/pngsuite/basi2c16.png", None);
1997 trial("tests/pngsuite/basi3p01.png", None);
1998 trial("tests/pngsuite/basi3p02.png", None);
1999 trial("tests/pngsuite/basi3p04.png", None);
2000 trial("tests/pngsuite/basi3p08.png", None);
2001 trial("tests/pngsuite/basi4a08.png", None);
2002 trial("tests/pngsuite/basi4a16.png", None);
2003 trial("tests/pngsuite/basi6a08.png", None);
2004 trial("tests/pngsuite/basi6a16.png", None);
2005 trial("tests/pngsuite/basn0g01.png", None);
2006 trial("tests/pngsuite/basn0g02.png", None);
2007 trial("tests/pngsuite/basn0g04.png", None);
2008 trial("tests/pngsuite/basn0g08.png", None);
2009 trial("tests/pngsuite/basn0g16.png", None);
2010 trial("tests/pngsuite/basn2c08.png", None);
2011 trial("tests/pngsuite/basn2c16.png", None);
2012 trial("tests/pngsuite/basn3p01.png", None);
2013 trial("tests/pngsuite/basn3p02.png", None);
2014 trial("tests/pngsuite/basn3p04.png", None);
2015 trial("tests/pngsuite/basn3p08.png", None);
2016 trial("tests/pngsuite/basn4a08.png", None);
2017 trial("tests/pngsuite/basn4a16.png", None);
2018 trial("tests/pngsuite/basn6a08.png", None);
2019 trial("tests/pngsuite/basn6a16.png", None);
2020 trial("tests/pngsuite/bgai4a08.png", None);
2021 trial("tests/pngsuite/bgai4a16.png", None);
2022 trial("tests/pngsuite/bgan6a08.png", None);
2023 trial("tests/pngsuite/bgan6a16.png", None);
2024 trial("tests/pngsuite/bgbn4a08.png", None);
2025 trial("tests/pngsuite/bggn4a16.png", None);
2026 trial("tests/pngsuite/bgwn6a08.png", None);
2027 trial("tests/pngsuite/bgyn6a16.png", None);
2028 trial("tests/pngsuite/cdfn2c08.png", None);
2029 trial("tests/pngsuite/cdhn2c08.png", None);
2030 trial("tests/pngsuite/cdsn2c08.png", None);
2031 trial("tests/pngsuite/cdun2c08.png", None);
2032 trial("tests/pngsuite/ch1n3p04.png", None);
2033 trial("tests/pngsuite/ch2n3p08.png", None);
2034 trial("tests/pngsuite/cm0n0g04.png", None);
2035 trial("tests/pngsuite/cm7n0g04.png", None);
2036 trial("tests/pngsuite/cm9n0g04.png", None);
2037 trial("tests/pngsuite/cs3n2c16.png", None);
2038 trial("tests/pngsuite/cs3n3p08.png", None);
2039 trial("tests/pngsuite/cs5n2c08.png", None);
2040 trial("tests/pngsuite/cs5n3p08.png", None);
2041 trial("tests/pngsuite/cs8n2c08.png", None);
2042 trial("tests/pngsuite/cs8n3p08.png", None);
2043 trial("tests/pngsuite/ct0n0g04.png", None);
2044 trial("tests/pngsuite/ct1n0g04.png", None);
2045 trial("tests/pngsuite/cten0g04.png", None);
2046 trial("tests/pngsuite/ctfn0g04.png", None);
2047 trial("tests/pngsuite/ctgn0g04.png", None);
2048 trial("tests/pngsuite/cthn0g04.png", None);
2049 trial("tests/pngsuite/ctjn0g04.png", None);
2050 trial("tests/pngsuite/ctzn0g04.png", None);
2051 trial("tests/pngsuite/f00n0g08.png", None);
2052 trial("tests/pngsuite/f00n2c08.png", None);
2053 trial("tests/pngsuite/f01n0g08.png", None);
2054 trial("tests/pngsuite/f01n2c08.png", None);
2055 trial("tests/pngsuite/f02n0g08.png", None);
2056 trial("tests/pngsuite/f02n2c08.png", None);
2057 trial("tests/pngsuite/f03n0g08.png", None);
2058 trial("tests/pngsuite/f03n2c08.png", None);
2059 trial("tests/pngsuite/f04n0g08.png", None);
2060 trial("tests/pngsuite/f04n2c08.png", None);
2061 trial("tests/pngsuite/f99n0g04.png", None);
2062 trial("tests/pngsuite/g03n0g16.png", None);
2063 trial("tests/pngsuite/g03n2c08.png", None);
2064 trial("tests/pngsuite/g03n3p04.png", None);
2065 trial("tests/pngsuite/g04n0g16.png", None);
2066 trial("tests/pngsuite/g04n2c08.png", None);
2067 trial("tests/pngsuite/g04n3p04.png", None);
2068 trial("tests/pngsuite/g05n0g16.png", None);
2069 trial("tests/pngsuite/g05n2c08.png", None);
2070 trial("tests/pngsuite/g05n3p04.png", None);
2071 trial("tests/pngsuite/g07n0g16.png", None);
2072 trial("tests/pngsuite/g07n2c08.png", None);
2073 trial("tests/pngsuite/g07n3p04.png", None);
2074 trial("tests/pngsuite/g10n0g16.png", None);
2075 trial("tests/pngsuite/g10n2c08.png", None);
2076 trial("tests/pngsuite/g10n3p04.png", None);
2077 trial("tests/pngsuite/g25n0g16.png", None);
2078 trial("tests/pngsuite/g25n2c08.png", None);
2079 trial("tests/pngsuite/g25n3p04.png", None);
2080 trial("tests/pngsuite/oi1n0g16.png", None);
2081 trial("tests/pngsuite/oi1n2c16.png", None);
2082 trial("tests/pngsuite/oi2n0g16.png", None);
2083 trial("tests/pngsuite/oi2n2c16.png", None);
2084 trial("tests/pngsuite/oi4n0g16.png", None);
2085 trial("tests/pngsuite/oi4n2c16.png", None);
2086 trial("tests/pngsuite/oi9n0g16.png", None);
2087 trial("tests/pngsuite/oi9n2c16.png", None);
2088 trial("tests/pngsuite/PngSuite.png", None);
2089 trial("tests/pngsuite/pp0n2c16.png", None);
2090 trial("tests/pngsuite/pp0n6a08.png", None);
2091 trial("tests/pngsuite/ps1n0g08.png", None);
2092 trial("tests/pngsuite/ps1n2c16.png", None);
2093 trial("tests/pngsuite/ps2n0g08.png", None);
2094 trial("tests/pngsuite/ps2n2c16.png", None);
2095 trial("tests/pngsuite/s01i3p01.png", None);
2096 trial("tests/pngsuite/s01n3p01.png", None);
2097 trial("tests/pngsuite/s02i3p01.png", None);
2098 trial("tests/pngsuite/s02n3p01.png", None);
2099 trial("tests/pngsuite/s03i3p01.png", None);
2100 trial("tests/pngsuite/s03n3p01.png", None);
2101 trial("tests/pngsuite/s04i3p01.png", None);
2102 trial("tests/pngsuite/s04n3p01.png", None);
2103 trial("tests/pngsuite/s05i3p02.png", None);
2104 trial("tests/pngsuite/s05n3p02.png", None);
2105 trial("tests/pngsuite/s06i3p02.png", None);
2106 trial("tests/pngsuite/s06n3p02.png", None);
2107 trial("tests/pngsuite/s07i3p02.png", None);
2108 trial("tests/pngsuite/s07n3p02.png", None);
2109 trial("tests/pngsuite/s08i3p02.png", None);
2110 trial("tests/pngsuite/s08n3p02.png", None);
2111 trial("tests/pngsuite/s09i3p02.png", None);
2112 trial("tests/pngsuite/s09n3p02.png", None);
2113 trial("tests/pngsuite/s32i3p04.png", None);
2114 trial("tests/pngsuite/s32n3p04.png", None);
2115 trial("tests/pngsuite/s33i3p04.png", None);
2116 trial("tests/pngsuite/s33n3p04.png", None);
2117 trial("tests/pngsuite/s34i3p04.png", None);
2118 trial("tests/pngsuite/s34n3p04.png", None);
2119 trial("tests/pngsuite/s35i3p04.png", None);
2120 trial("tests/pngsuite/s35n3p04.png", None);
2121 trial("tests/pngsuite/s36i3p04.png", None);
2122 trial("tests/pngsuite/s36n3p04.png", None);
2123 trial("tests/pngsuite/s37i3p04.png", None);
2124 trial("tests/pngsuite/s37n3p04.png", None);
2125 trial("tests/pngsuite/s38i3p04.png", None);
2126 trial("tests/pngsuite/s38n3p04.png", None);
2127 trial("tests/pngsuite/s39i3p04.png", None);
2128 trial("tests/pngsuite/s39n3p04.png", None);
2129 trial("tests/pngsuite/s40i3p04.png", None);
2130 trial("tests/pngsuite/s40n3p04.png", None);
2131 trial("tests/pngsuite/tbbn0g04.png", None);
2132 trial("tests/pngsuite/tbbn2c16.png", None);
2133 trial("tests/pngsuite/tbbn3p08.png", None);
2134 trial("tests/pngsuite/tbgn2c16.png", None);
2135 trial("tests/pngsuite/tbgn3p08.png", None);
2136 trial("tests/pngsuite/tbrn2c08.png", None);
2137 trial("tests/pngsuite/tbwn0g16.png", None);
2138 trial("tests/pngsuite/tbwn3p08.png", None);
2139 trial("tests/pngsuite/tbyn3p08.png", None);
2140 trial("tests/pngsuite/tm3n3p02.png", None);
2141 trial("tests/pngsuite/tp0n0g08.png", None);
2142 trial("tests/pngsuite/tp0n2c08.png", None);
2143 trial("tests/pngsuite/tp0n3p08.png", None);
2144 trial("tests/pngsuite/tp1n3p08.png", None);
2145 trial("tests/pngsuite/z00n2c08.png", None);
2146 trial("tests/pngsuite/z03n2c08.png", None);
2147 trial("tests/pngsuite/z06n2c08.png", None);
2148 Ok(())
2149 }
2150
2151 #[test]
2152 fn image_source_sbit() {
2153 fn trial(path: &str, expected: Option<Cow<[u8]>>) {
2154 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
2155 let reader = decoder.read_info().unwrap();
2156 let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
2157 assert!(actual == expected);
2158 }
2159
2160 trial("tests/sbit/g.png", Some(Cow::Owned(vec![5u8])));
2161 trial("tests/sbit/ga.png", Some(Cow::Owned(vec![5u8, 3u8])));
2162 trial(
2163 "tests/sbit/indexed.png",
2164 Some(Cow::Owned(vec![5u8, 6u8, 5u8])),
2165 );
2166 trial("tests/sbit/rgb.png", Some(Cow::Owned(vec![5u8, 6u8, 5u8])));
2167 trial(
2168 "tests/sbit/rgba.png",
2169 Some(Cow::Owned(vec![5u8, 6u8, 5u8, 8u8])),
2170 );
2171 }
2172
2173 #[test]
2176 fn test_two_iccp_chunks() {
2177 let decoder = crate::Decoder::new(BufReader::new(
2182 File::open("tests/bugfixes/issue#1825.png").unwrap(),
2183 ));
2184 let reader = decoder.read_info().unwrap();
2185 let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
2186
2187 assert_eq!(4070462061, crc32fast::hash(&icc_profile));
2192 }
2193
2194 #[test]
2195 fn test_iccp_roundtrip() {
2196 let dummy_icc = b"I'm a profile";
2197
2198 let mut info = crate::Info::with_size(1, 1);
2199 info.icc_profile = Some(dummy_icc.into());
2200 let mut encoded_image = Vec::new();
2201 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2202 let mut enc = enc.write_header().unwrap();
2203 enc.write_image_data(&[0]).unwrap();
2204 enc.finish().unwrap();
2205
2206 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2207 let dec = dec.read_info().unwrap();
2208 assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap());
2209 }
2210
2211 #[test]
2212 fn test_phys_roundtrip() {
2213 let mut info = crate::Info::with_size(1, 1);
2214 info.pixel_dims = Some(crate::PixelDimensions {
2215 xppu: 12,
2216 yppu: 34,
2217 unit: Unit::Meter,
2218 });
2219 let mut encoded_image = Vec::new();
2220 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2221 let mut enc = enc.write_header().unwrap();
2222 enc.write_image_data(&[0]).unwrap();
2223 enc.finish().unwrap();
2224
2225 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2226 let dec = dec.read_info().unwrap();
2227 let phys = dec.info().pixel_dims.as_ref().unwrap();
2228 assert_eq!(phys.xppu, 12);
2229 assert_eq!(phys.yppu, 34);
2230 assert_eq!(phys.unit, Unit::Meter);
2231 }
2232
2233 #[test]
2234 fn test_srgb_roundtrip() {
2235 let mut info = crate::Info::with_size(1, 1);
2236 info.srgb = Some(SrgbRenderingIntent::Saturation);
2237 let mut encoded_image = Vec::new();
2238 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2239 let mut enc = enc.write_header().unwrap();
2240 enc.write_image_data(&[0]).unwrap();
2241 enc.finish().unwrap();
2242
2243 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2244 let dec = dec.read_info().unwrap();
2245 assert_eq!(dec.info().srgb.unwrap(), SrgbRenderingIntent::Saturation);
2246 }
2247
2248 #[test]
2249 fn test_png_with_broken_iccp() {
2250 let decoder = crate::Decoder::new(BufReader::new(
2251 File::open("tests/iccp/broken_iccp.png").unwrap(),
2252 ));
2253 assert!(decoder.read_info().is_ok());
2254 let mut decoder = crate::Decoder::new(BufReader::new(
2255 File::open("tests/iccp/broken_iccp.png").unwrap(),
2256 ));
2257 decoder.set_ignore_iccp_chunk(true);
2258 assert!(decoder.read_info().is_ok());
2259 }
2260
2261 #[test]
2263 fn test_cicp_mdcv_and_clli_chunks() {
2264 let mut decoder = crate::Decoder::new(BufReader::new(
2265 File::open("tests/bugfixes/cicp_pq.png").unwrap(),
2266 ));
2267 decoder.ignore_checksums(true);
2268 let reader = decoder.read_info().unwrap();
2269 let info = reader.info();
2270
2271 let cicp = info.coding_independent_code_points.unwrap();
2272 assert_eq!(cicp.color_primaries, 9);
2273 assert_eq!(cicp.transfer_function, 16);
2274 assert_eq!(cicp.matrix_coefficients, 0);
2275 assert!(cicp.is_video_full_range_image);
2276
2277 let mdcv = info.mastering_display_color_volume.unwrap();
2278 assert_relative_eq!(mdcv.chromaticities.red.0.into_value(), 0.680);
2279 assert_relative_eq!(mdcv.chromaticities.red.1.into_value(), 0.320);
2280 assert_relative_eq!(mdcv.chromaticities.green.0.into_value(), 0.265);
2281 assert_relative_eq!(mdcv.chromaticities.green.1.into_value(), 0.690);
2282 assert_relative_eq!(mdcv.chromaticities.blue.0.into_value(), 0.150);
2283 assert_relative_eq!(mdcv.chromaticities.blue.1.into_value(), 0.060);
2284 assert_relative_eq!(mdcv.chromaticities.white.0.into_value(), 0.3127);
2285 assert_relative_eq!(mdcv.chromaticities.white.1.into_value(), 0.3290);
2286 assert_relative_eq!(mdcv.min_luminance as f32 / 10_000.0, 0.01);
2287 assert_relative_eq!(mdcv.max_luminance as f32 / 10_000.0, 5000.0);
2288
2289 let clli = info.content_light_level.unwrap();
2290 assert_relative_eq!(clli.max_content_light_level as f32 / 10_000.0, 4000.0);
2291 assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0);
2292 }
2293
2294 #[test]
2296 fn test_exif_chunk() {
2297 let decoder = crate::Decoder::new(BufReader::new(
2298 File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap(),
2299 ));
2300 let reader = decoder.read_info().unwrap();
2301 let info = reader.info();
2302 let exif = info.exif_metadata.as_ref().unwrap().as_ref();
2303 assert_eq!(exif.len(), 90);
2304 }
2305
2306 #[test]
2308 fn test_finishing_twice() {
2309 let mut png = Vec::new();
2310 write_noncompressed_png(&mut png, 16, 1024);
2311 let decoder = Decoder::new(Cursor::new(&png));
2312 let mut reader = decoder.read_info().unwrap();
2313
2314 reader.finish().unwrap();
2316
2317 let err = reader.finish().unwrap_err();
2319 assert!(matches!(&err, DecodingError::Parameter(_)));
2320 assert_eq!("End of image has been reached", format!("{err}"));
2321 }
2322
2323 fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) {
2326 let mut data = Vec::new();
2327 data.write_u32::<byteorder::BigEndian>(animation.num_frames)
2328 .unwrap();
2329 data.write_u32::<byteorder::BigEndian>(animation.num_plays)
2330 .unwrap();
2331 write_chunk(w, b"acTL", &data);
2332 }
2333
2334 fn write_fctl(w: &mut impl Write, frame: &crate::FrameControl) {
2337 let mut data = Vec::new();
2338 data.write_u32::<byteorder::BigEndian>(frame.sequence_number)
2339 .unwrap();
2340 data.write_u32::<byteorder::BigEndian>(frame.width).unwrap();
2341 data.write_u32::<byteorder::BigEndian>(frame.height)
2342 .unwrap();
2343 data.write_u32::<byteorder::BigEndian>(frame.x_offset)
2344 .unwrap();
2345 data.write_u32::<byteorder::BigEndian>(frame.y_offset)
2346 .unwrap();
2347 data.write_u16::<byteorder::BigEndian>(frame.delay_num)
2348 .unwrap();
2349 data.write_u16::<byteorder::BigEndian>(frame.delay_den)
2350 .unwrap();
2351 data.write_u8(frame.dispose_op as u8).unwrap();
2352 data.write_u8(frame.blend_op as u8).unwrap();
2353 write_chunk(w, b"fcTL", &data);
2354 }
2355
2356 fn write_fdat(w: &mut impl Write, sequence_number: u32, image_data: &[u8]) {
2359 let mut data = Vec::new();
2360 data.write_u32::<byteorder::BigEndian>(sequence_number)
2361 .unwrap();
2362 data.write_all(image_data).unwrap();
2363 write_chunk(w, b"fdAT", &data);
2364 }
2365
2366 fn write_fdat_prefix(w: &mut impl Write, num_frames: u32, width: u32) {
2371 write_png_sig(w);
2372 write_rgba8_ihdr_with_width(w, width);
2373 write_actl(
2374 w,
2375 &crate::AnimationControl {
2376 num_frames,
2377 num_plays: 0,
2378 },
2379 );
2380
2381 let mut fctl = crate::FrameControl {
2382 width,
2383 height: width,
2384 ..Default::default()
2385 };
2386 write_fctl(w, &fctl);
2387 write_rgba8_idats(w, width, 0x7fffffff);
2388
2389 fctl.sequence_number += 1;
2390 write_fctl(w, &fctl);
2391 }
2392
2393 #[test]
2394 fn test_fdat_chunk_payload_length_0() {
2395 let mut png = Vec::new();
2396 write_fdat_prefix(&mut png, 2, 8);
2397 write_chunk(&mut png, b"fdAT", &[]);
2398
2399 let decoder = Decoder::new(Cursor::new(&png));
2400 let mut reader = decoder.read_info().unwrap();
2401 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2402 reader.next_frame(&mut buf).unwrap();
2403
2404 let err = reader.next_frame(&mut buf).unwrap_err();
2406 assert!(matches!(&err, DecodingError::Format(_)));
2407 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2408
2409 let err2 = reader.next_frame(&mut buf).unwrap_err();
2414 assert!(matches!(&err2, DecodingError::Parameter(_)));
2415 assert_eq!(
2416 "A fatal decoding error has been encounted earlier",
2417 format!("{err2}")
2418 );
2419 }
2420
2421 #[test]
2422 fn test_fdat_chunk_payload_length_3() {
2423 let mut png = Vec::new();
2424 write_fdat_prefix(&mut png, 2, 8);
2425 write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
2426
2427 let decoder = Decoder::new(Cursor::new(&png));
2428 let mut reader = decoder.read_info().unwrap();
2429 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2430 reader.next_frame(&mut buf).unwrap();
2431
2432 let err = reader.next_frame(&mut buf).unwrap_err();
2434 assert!(matches!(&err, DecodingError::Format(_)));
2435 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2436 }
2437
2438 #[test]
2439 fn test_frame_split_across_two_fdat_chunks() {
2440 let png = {
2455 let mut png = Vec::new();
2456 write_fdat_prefix(&mut png, 2, 8);
2457 let image_data = generate_rgba8_with_width_and_height(8, 8);
2458 write_fdat(&mut png, 2, &image_data[..30]);
2459 write_fdat(&mut png, 3, &image_data[30..]);
2460 write_iend(&mut png);
2461 png
2462 };
2463
2464 let decoder = Decoder::new(Cursor::new(&png));
2466 let mut reader = decoder.read_info().unwrap();
2467 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2468 let Some(animation_control) = reader.info().animation_control else {
2469 panic!("No acTL");
2470 };
2471 assert_eq!(animation_control.num_frames, 2);
2472
2473 let first_frame: Vec<u8>;
2475 {
2476 reader.next_frame(&mut buf).unwrap();
2477 first_frame = buf.clone();
2478
2479 let Some(frame_control) = reader.info().frame_control else {
2483 panic!("No fcTL (1st frame)");
2484 };
2485 assert_eq!(frame_control.sequence_number, 0);
2488 }
2489
2490 let second_frame: Vec<u8>;
2492 {
2493 reader.next_frame(&mut buf).unwrap();
2494 second_frame = buf.clone();
2495
2496 let Some(frame_control) = reader.info().frame_control else {
2498 panic!("No fcTL (2nd frame)");
2499 };
2500 assert_eq!(frame_control.sequence_number, 1);
2504 }
2505
2506 assert_eq!(first_frame, second_frame);
2507 }
2508
2509 #[test]
2510 fn test_idat_bigger_than_image_size_from_ihdr() {
2511 let png = {
2512 let mut png = Vec::new();
2513 write_png_sig(&mut png);
2514 write_rgba8_ihdr_with_width(&mut png, 8);
2515
2516 write_chunk(
2520 &mut png,
2521 b"IDAT",
2522 &generate_rgba8_with_width_and_height(8, 256),
2523 );
2524
2525 write_iend(&mut png);
2526 png
2527 };
2528 let decoder = Decoder::new(Cursor::new(&png));
2529 let mut reader = decoder.read_info().unwrap();
2530 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2531
2532 reader.next_frame(&mut buf).unwrap();
2535 assert_eq!(3093270825, crc32fast::hash(&buf));
2536 }
2537
2538 #[test]
2539 fn test_only_idat_chunk_in_input_stream() {
2540 let png = {
2541 let mut png = Vec::new();
2542 write_png_sig(&mut png);
2543 write_chunk(&mut png, b"IDAT", &[]);
2544 png
2545 };
2546 let decoder = Decoder::new(Cursor::new(&png));
2547 let Err(err) = decoder.read_info() else {
2548 panic!("Expected an error")
2549 };
2550 assert!(matches!(&err, DecodingError::Format(_)));
2551 assert_eq!(
2552 "ChunkType { type: IDAT, \
2553 critical: true, \
2554 private: false, \
2555 reserved: false, \
2556 safecopy: false \
2557 } chunk appeared before IHDR chunk",
2558 format!("{err}"),
2559 );
2560 }
2561
2562 #[derive(Clone)]
2565 struct StreamingInput {
2566 full_input: Vec<u8>,
2567 state: Rc<RefCell<StreamingInputState>>,
2568 }
2569
2570 struct StreamingInputState {
2571 current_pos: usize,
2572 available_len: usize,
2573 }
2574
2575 impl StreamingInput {
2576 fn new(full_input: Vec<u8>) -> Self {
2577 Self {
2578 full_input,
2579 state: Rc::new(RefCell::new(StreamingInputState {
2580 current_pos: 0,
2581 available_len: 0,
2582 })),
2583 }
2584 }
2585
2586 fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
2587 let mut png = Vec::new();
2588 write_noncompressed_png(&mut png, width, idat_size);
2589 Self::new(png)
2590 }
2591
2592 fn expose_next_byte(&self) {
2593 let mut state = self.state.borrow_mut();
2594 assert!(state.available_len < self.full_input.len());
2595 state.available_len += 1;
2596 }
2597
2598 fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
2599 loop {
2600 self.state.borrow_mut().current_pos = 0;
2601 match Decoder::new(self.clone()).read_info() {
2602 Ok(reader) => {
2603 break reader;
2604 }
2605 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2606 self.expose_next_byte();
2607 }
2608 _ => panic!("Unexpected error"),
2609 }
2610 }
2611 }
2612
2613 fn decode_full_input<F, R>(&self, f: F) -> R
2614 where
2615 F: FnOnce(Reader<Cursor<&[u8]>>) -> R,
2616 {
2617 let decoder = Decoder::new(Cursor::new(&*self.full_input));
2618 f(decoder.read_info().unwrap())
2619 }
2620 }
2621
2622 impl Read for StreamingInput {
2623 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
2624 let mut state = self.state.borrow_mut();
2625 let mut available_bytes = &self.full_input[state.current_pos..state.available_len];
2626 let number_of_read_bytes = available_bytes.read(buf)?;
2627 state.current_pos += number_of_read_bytes;
2628 assert!(state.current_pos <= state.available_len);
2629 Ok(number_of_read_bytes)
2630 }
2631 }
2632 impl BufRead for StreamingInput {
2633 fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
2634 let state = self.state.borrow();
2635 Ok(&self.full_input[state.current_pos..state.available_len])
2636 }
2637
2638 fn consume(&mut self, amt: usize) {
2639 let mut state = self.state.borrow_mut();
2640 state.current_pos += amt;
2641 assert!(state.current_pos <= state.available_len);
2642 }
2643 }
2644 impl Seek for StreamingInput {
2645 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
2646 let mut state = self.state.borrow_mut();
2647 state.current_pos = match pos {
2648 std::io::SeekFrom::Start(n) => n as usize,
2649 std::io::SeekFrom::End(n) => (self.full_input.len() as i64 + n) as usize,
2650 std::io::SeekFrom::Current(n) => (state.current_pos as i64 + n) as usize,
2651 } as usize;
2652 Ok(state.current_pos as u64)
2653 }
2654 fn stream_position(&mut self) -> std::io::Result<u64> {
2655 Ok(self.state.borrow().current_pos as u64)
2656 }
2657 }
2658
2659 #[test]
2661 fn test_streaming_input_and_decoding_via_next_frame() {
2662 const WIDTH: u32 = 16;
2663 const IDAT_SIZE: usize = 512;
2664 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2665
2666 let (whole_output_info, decoded_from_whole_input) =
2667 streaming_input.decode_full_input(|mut r| {
2668 let mut buf = vec![0; r.output_buffer_size().unwrap()];
2669 let output_info = r.next_frame(&mut buf).unwrap();
2670 (output_info, buf)
2671 });
2672
2673 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2674 let mut decoded_from_streaming_input = vec![0; png_reader.output_buffer_size().unwrap()];
2675 let streaming_output_info = loop {
2676 match png_reader.next_frame(decoded_from_streaming_input.as_mut_slice()) {
2677 Ok(output_info) => break output_info,
2678 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2679 streaming_input.expose_next_byte()
2680 }
2681 e => panic!("Unexpected error: {:?}", e),
2682 }
2683 };
2684 assert_eq!(whole_output_info, streaming_output_info);
2685 assert_eq!(
2686 crc32fast::hash(&decoded_from_whole_input),
2687 crc32fast::hash(&decoded_from_streaming_input)
2688 );
2689 }
2690
2691 #[test]
2693 fn test_streaming_input_and_decoding_via_next_row() {
2694 const WIDTH: u32 = 16;
2695 const IDAT_SIZE: usize = 512;
2696 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2697
2698 let decoded_from_whole_input = streaming_input.decode_full_input(|mut r| {
2699 let mut buf = vec![0; r.output_buffer_size().unwrap()];
2700 r.next_frame(&mut buf).unwrap();
2701 buf
2702 });
2703
2704 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2705 let mut decoded_from_streaming_input = Vec::new();
2706 loop {
2707 match png_reader.next_row() {
2708 Ok(None) => break,
2709 Ok(Some(row)) => decoded_from_streaming_input.extend_from_slice(row.data()),
2710 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2711 streaming_input.expose_next_byte()
2712 }
2713 e => panic!("Unexpected error: {:?}", e),
2714 }
2715 }
2716 assert_eq!(
2717 crc32fast::hash(&decoded_from_whole_input),
2718 crc32fast::hash(&decoded_from_streaming_input)
2719 );
2720 }
2721
2722 #[test]
2724 fn test_streaming_input_and_reading_header_info() {
2725 const WIDTH: u32 = 16;
2726 const IDAT_SIZE: usize = 512;
2727 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2728
2729 let info_from_whole_input = streaming_input.decode_full_input(|r| r.info().clone());
2730
2731 let mut decoder = Decoder::new(streaming_input.clone());
2732 let info_from_streaming_input = loop {
2733 match decoder.read_header_info() {
2734 Ok(info) => break info.clone(),
2735 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2736 streaming_input.expose_next_byte()
2737 }
2738 e => panic!("Unexpected error: {:?}", e),
2739 }
2740 };
2741
2742 assert_eq!(info_from_whole_input.width, info_from_streaming_input.width);
2743 assert_eq!(
2744 info_from_whole_input.height,
2745 info_from_streaming_input.height
2746 );
2747 assert_eq!(
2748 info_from_whole_input.bit_depth,
2749 info_from_streaming_input.bit_depth
2750 );
2751 assert_eq!(
2752 info_from_whole_input.color_type,
2753 info_from_streaming_input.color_type
2754 );
2755 assert_eq!(
2756 info_from_whole_input.interlaced,
2757 info_from_streaming_input.interlaced
2758 );
2759 }
2760
2761 fn create_reader_of_ihdr_idat() -> Reader<Cursor<Vec<u8>>> {
2764 let mut png = Vec::new();
2765 write_noncompressed_png(&mut png, 16, 1024);
2766 Decoder::new(Cursor::new(png)).read_info().unwrap()
2767 }
2768
2769 fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
2772 let width = 16;
2773 let mut fctl = crate::FrameControl {
2774 width,
2775 height: width,
2776 ..Default::default()
2777 };
2778
2779 let mut png = Vec::new();
2780 write_png_sig(&mut png);
2781 write_rgba8_ihdr_with_width(&mut png, width);
2782 write_actl(
2783 &mut png,
2784 &crate::AnimationControl {
2785 num_frames: 2,
2786 num_plays: 0,
2787 },
2788 );
2789 fctl.sequence_number = 0;
2790 write_fctl(&mut png, &fctl);
2791 let idat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height + 1);
2795 write_chunk(&mut png, b"IDAT", &idat_data);
2796
2797 let fdat_width = 10;
2798 fctl.sequence_number = 1;
2799 fctl.width = fdat_width;
2803 write_fctl(&mut png, &fctl);
2804 let fdat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height);
2805 write_fdat(&mut png, 2, &fdat_data);
2806 write_iend(&mut png);
2807
2808 Decoder::new(Cursor::new(png)).read_info().unwrap()
2809 }
2810
2811 fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
2814 let width = 16;
2815 let frame_data = generate_rgba8_with_width_and_height(width, width);
2816 let mut fctl = crate::FrameControl {
2817 width,
2818 height: width,
2819 ..Default::default()
2820 };
2821
2822 let mut png = Vec::new();
2823 write_png_sig(&mut png);
2824 write_rgba8_ihdr_with_width(&mut png, width);
2825 write_actl(
2826 &mut png,
2827 &crate::AnimationControl {
2828 num_frames: 2,
2829 num_plays: 0,
2830 },
2831 );
2832 write_chunk(&mut png, b"IDAT", &frame_data);
2833 fctl.sequence_number = 0;
2834 write_fctl(&mut png, &fctl);
2835 write_fdat(&mut png, 1, &frame_data);
2836 fctl.sequence_number = 2;
2837 write_fctl(&mut png, &fctl);
2838 write_fdat(&mut png, 3, &frame_data);
2839 write_iend(&mut png);
2840
2841 Decoder::new(Cursor::new(png)).read_info().unwrap()
2842 }
2843
2844 fn get_fctl_sequence_number(reader: &Reader<impl BufRead + Seek>) -> u32 {
2845 reader
2846 .info()
2847 .frame_control
2848 .as_ref()
2849 .unwrap()
2850 .sequence_number
2851 }
2852
2853 #[test]
2856 fn test_next_frame_polling_after_end_non_animated() {
2857 let mut reader = create_reader_of_ihdr_idat();
2858 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2859 reader
2860 .next_frame(&mut buf)
2861 .expect("Expecting no error for IDAT frame");
2862
2863 let err = reader
2864 .next_frame(&mut buf)
2865 .expect_err("Main test - expecting error");
2866 assert!(
2867 matches!(&err, DecodingError::Parameter(_)),
2868 "Unexpected kind of error: {:?}",
2869 &err,
2870 );
2871 }
2872
2873 #[test]
2876 fn test_next_frame_info_polling_after_end_non_animated() {
2877 let mut reader = create_reader_of_ihdr_idat();
2878
2879 let err = reader
2880 .next_frame_info()
2881 .expect_err("Main test - expecting error");
2882 assert!(
2883 matches!(&err, DecodingError::Parameter(_)),
2884 "Unexpected kind of error: {:?}",
2885 &err,
2886 );
2887 }
2888
2889 #[test]
2893 fn test_next_frame_polling_after_end_idat_part_of_animation() {
2894 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2895 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2896
2897 assert_eq!(get_fctl_sequence_number(&reader), 0);
2898 reader
2899 .next_frame(&mut buf)
2900 .expect("Expecting no error for IDAT frame");
2901
2902 assert_eq!(get_fctl_sequence_number(&reader), 0);
2904
2905 reader
2906 .next_frame(&mut buf)
2907 .expect("Expecting no error for fdAT frame");
2908 assert_eq!(get_fctl_sequence_number(&reader), 1);
2909
2910 let err = reader
2911 .next_frame(&mut buf)
2912 .expect_err("Main test - expecting error");
2913 assert!(
2914 matches!(&err, DecodingError::Parameter(_)),
2915 "Unexpected kind of error: {:?}",
2916 &err,
2917 );
2918 }
2919
2920 #[test]
2924 fn test_next_frame_polling_after_end_idat_not_part_of_animation() {
2925 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
2926 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2927
2928 assert!(reader.info().frame_control.is_none());
2929 reader
2930 .next_frame(&mut buf)
2931 .expect("Expecting no error for IDAT frame");
2932
2933 assert!(reader.info().frame_control.is_none());
2935
2936 reader
2937 .next_frame(&mut buf)
2938 .expect("Expecting no error for 1st fdAT frame");
2939 assert_eq!(get_fctl_sequence_number(&reader), 0);
2940
2941 reader
2942 .next_frame(&mut buf)
2943 .expect("Expecting no error for 2nd fdAT frame");
2944 assert_eq!(get_fctl_sequence_number(&reader), 2);
2945
2946 let err = reader
2947 .next_frame(&mut buf)
2948 .expect_err("Main test - expecting error");
2949 assert!(
2950 matches!(&err, DecodingError::Parameter(_)),
2951 "Unexpected kind of error: {:?}",
2952 &err,
2953 );
2954 }
2955
2956 #[test]
2959 fn test_row_by_row_then_next_frame() {
2960 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2961 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2962
2963 assert_eq!(get_fctl_sequence_number(&reader), 0);
2964 while let Some(_) = reader.next_row().unwrap() {}
2965 assert_eq!(get_fctl_sequence_number(&reader), 0);
2966
2967 buf.fill(0x0f);
2968 reader
2969 .next_frame(&mut buf)
2970 .expect("Expecting no error from next_frame call");
2971
2972 assert_eq!(get_fctl_sequence_number(&reader), 1);
2974 assert!(buf.iter().any(|byte| *byte != 0x0f));
2975 }
2976
2977 #[test]
2981 fn test_row_by_row_of_two_frames() {
2982 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
2983
2984 let mut rows_of_frame1 = 0;
2985 assert_eq!(get_fctl_sequence_number(&reader), 0);
2986 while let Some(_) = reader.next_row().unwrap() {
2987 rows_of_frame1 += 1;
2988 }
2989 assert_eq!(rows_of_frame1, 16);
2990 assert_eq!(get_fctl_sequence_number(&reader), 0);
2991
2992 let mut rows_of_frame2 = 0;
2993 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
2994 assert_eq!(get_fctl_sequence_number(&reader), 1);
2995 while let Some(_) = reader.next_row().unwrap() {
2996 rows_of_frame2 += 1;
2997 }
2998 assert_eq!(rows_of_frame2, 16);
2999 assert_eq!(get_fctl_sequence_number(&reader), 1);
3000
3001 let err = reader
3002 .next_frame_info()
3003 .expect_err("No more frames - expecting error");
3004 assert!(
3005 matches!(&err, DecodingError::Parameter(_)),
3006 "Unexpected kind of error: {:?}",
3007 &err,
3008 );
3009 }
3010
3011 #[test]
3017 fn test_next_frame_info_after_next_frame() {
3018 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
3019 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3020
3021 assert_eq!(get_fctl_sequence_number(&reader), 0);
3022 reader
3023 .next_frame(&mut buf)
3024 .expect("Expecting no error for IDAT frame");
3025
3026 assert_eq!(get_fctl_sequence_number(&reader), 0);
3028
3029 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
3031 assert_eq!(get_fctl_sequence_number(&reader), 1);
3032
3033 reader
3034 .next_frame(&mut buf)
3035 .expect("Expecting no error for fdAT frame");
3036 assert_eq!(get_fctl_sequence_number(&reader), 1);
3037
3038 let err = reader
3039 .next_frame_info()
3040 .expect_err("Main test - expecting error");
3041 assert!(
3042 matches!(&err, DecodingError::Parameter(_)),
3043 "Unexpected kind of error: {:?}",
3044 &err,
3045 );
3046 }
3047
3048 #[test]
3051 fn test_next_frame_info_to_skip_first_frame() {
3052 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
3053 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3054
3055 assert!(reader.info().frame_control.is_none());
3058
3059 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 0);
3062 assert_eq!(get_fctl_sequence_number(&reader), 0);
3063 reader
3064 .next_frame(&mut buf)
3065 .expect("Expecting no error for 1st fdAT frame");
3066 assert_eq!(get_fctl_sequence_number(&reader), 0);
3067
3068 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 2);
3070 reader
3071 .next_frame(&mut buf)
3072 .expect("Expecting no error for 2nd fdAT frame");
3073 assert_eq!(get_fctl_sequence_number(&reader), 2);
3074
3075 let err = reader
3076 .next_frame_info()
3077 .expect_err("Main test - expecting error");
3078 assert!(
3079 matches!(&err, DecodingError::Parameter(_)),
3080 "Unexpected kind of error: {:?}",
3081 &err,
3082 );
3083 }
3084
3085 #[test]
3086 fn test_incorrect_trns_chunk_is_ignored() {
3087 let png = {
3088 let mut png = Vec::new();
3089 write_png_sig(&mut png);
3090 write_rgba8_ihdr_with_width(&mut png, 8);
3091 write_chunk(&mut png, b"tRNS", &[12, 34, 56]);
3092 write_chunk(
3093 &mut png,
3094 b"IDAT",
3095 &generate_rgba8_with_width_and_height(8, 8),
3096 );
3097 write_iend(&mut png);
3098 png
3099 };
3100 let decoder = Decoder::new(Cursor::new(&png));
3101 let mut reader = decoder.read_info().unwrap();
3102 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3103 assert!(reader.info().trns.is_none());
3104 reader.next_frame(&mut buf).unwrap();
3105 assert_eq!(3093270825, crc32fast::hash(&buf));
3106 assert!(reader.info().trns.is_none());
3107 }
3108
3109 #[test]
3111 fn test_actl_num_frames_zero() {
3112 let width = 16;
3113 let frame_data = generate_rgba8_with_width_and_height(width, width);
3114
3115 let mut png = Vec::new();
3116 write_png_sig(&mut png);
3117 write_rgba8_ihdr_with_width(&mut png, width);
3118 write_actl(
3119 &mut png,
3120 &crate::AnimationControl {
3121 num_frames: 0, num_plays: 0,
3123 },
3124 );
3125 write_fctl(
3131 &mut png,
3132 &crate::FrameControl {
3133 width,
3134 height: width,
3135 ..Default::default()
3136 },
3137 );
3138 write_chunk(&mut png, b"IDAT", &frame_data);
3139 write_iend(&mut png);
3140
3141 let mut reader = Decoder::new(Cursor::new(png)).read_info().unwrap();
3142
3143 while let Some(_row) = reader.next_interlaced_row().unwrap() {}
3149 }
3150
3151 #[test]
3152 fn test_small_fctl() {
3153 const FCTL_SIZE: u32 = 30;
3154 const IHDR_SIZE: u32 = 50;
3155 let mut png = Vec::new();
3156 write_png_sig(&mut png);
3157 write_rgba8_ihdr_with_width(&mut png, IHDR_SIZE);
3158 write_actl(
3159 &mut png,
3160 &crate::AnimationControl {
3161 num_frames: 1,
3162 num_plays: 1,
3163 },
3164 );
3165 write_fctl(
3166 &mut png,
3167 &crate::FrameControl {
3168 width: FCTL_SIZE,
3169 height: FCTL_SIZE,
3170 x_offset: 10,
3171 y_offset: 10,
3172 sequence_number: 0,
3173 ..Default::default()
3174 },
3175 );
3176 write_chunk(
3177 &mut png,
3178 b"IDAT",
3179 &generate_rgba8_with_width_and_height(IHDR_SIZE, IHDR_SIZE),
3180 );
3181 write_iend(&mut png);
3182
3183 let reader = Decoder::new(Cursor::new(png)).read_info();
3184 let err = reader.err().unwrap();
3185 assert!(matches!(&err, DecodingError::Format(_)));
3186 assert_eq!("Sub frame is out-of-bounds.", format!("{err}"));
3187 }
3188
3189 #[test]
3190 fn test_invalid_text_chunk() {
3191 let invalid_text_chunk = vec![b'A'; 100];
3195
3196 const SIZE: u32 = 20;
3197 let mut png = Vec::new();
3198 write_png_sig(&mut png);
3199 write_rgba8_ihdr_with_width(&mut png, SIZE);
3200 write_chunk(&mut png, b"tEXt", invalid_text_chunk.as_slice());
3201 write_chunk(
3202 &mut png,
3203 b"IDAT",
3204 &generate_rgba8_with_width_and_height(SIZE, SIZE),
3205 );
3206 write_iend(&mut png);
3207
3208 let reader = Decoder::new(Cursor::new(png)).read_info().unwrap();
3209 let info = reader.info();
3210 assert_eq!(info.width, SIZE);
3211 assert_eq!(info.uncompressed_latin1_text.len(), 0);
3212 }
3213}