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 ChunkLengthWrong {
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 ChunkLengthWrong { kind } => {
419 write!(fmt, "Chunk length wrong: {:?}", 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 action: ChunkAction,
576}
577
578#[derive(Debug, PartialEq)]
579enum ChunkAction {
580 Process,
581 Skip,
582 Reject,
583}
584
585impl StreamingDecoder {
586 pub fn new() -> StreamingDecoder {
590 StreamingDecoder::new_with_options(DecodeOptions::default())
591 }
592
593 pub fn new_with_options(decode_options: DecodeOptions) -> StreamingDecoder {
594 let mut inflater = ZlibStream::new();
595 inflater.set_ignore_adler32(decode_options.ignore_adler32);
596
597 StreamingDecoder {
598 state: Some(State::new_u32(U32ValueKind::Signature1stU32)),
599 current_chunk: ChunkState {
600 type_: ChunkType([0; 4]),
601 crc: Crc32::new(),
602 remaining: 0,
603 raw_bytes: Vec::with_capacity(CHUNK_BUFFER_SIZE),
604 action: ChunkAction::Process,
605 },
606 inflater,
607 info: None,
608 current_seq_no: None,
609 have_idat: false,
610 have_iccp: false,
611 ready_for_idat_chunks: true,
612 ready_for_fdat_chunks: false,
613 decode_options,
614 limits: Limits { bytes: usize::MAX },
615 }
616 }
617
618 pub fn reset(&mut self) {
620 self.state = Some(State::new_u32(U32ValueKind::Signature1stU32));
621 self.current_chunk.crc = Crc32::new();
622 self.current_chunk.remaining = 0;
623 self.current_chunk.raw_bytes.clear();
624 self.inflater.reset();
625 self.info = None;
626 self.current_seq_no = None;
627 self.have_idat = false;
628 }
629
630 pub fn info(&self) -> Option<&Info<'static>> {
632 self.info.as_ref()
633 }
634
635 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
636 self.decode_options.set_ignore_text_chunk(ignore_text_chunk);
637 }
638
639 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
640 self.decode_options.set_ignore_iccp_chunk(ignore_iccp_chunk);
641 }
642
643 pub fn ignore_adler32(&self) -> bool {
645 self.inflater.ignore_adler32()
646 }
647
648 pub fn set_ignore_adler32(&mut self, ignore_adler32: bool) -> bool {
656 self.inflater.set_ignore_adler32(ignore_adler32)
657 }
658
659 pub fn set_ignore_crc(&mut self, ignore_crc: bool) {
664 self.decode_options.set_ignore_crc(ignore_crc)
665 }
666
667 pub fn set_skip_ancillary_crc_failures(&mut self, skip_ancillary_crc_failures: bool) {
671 self.decode_options
672 .set_skip_ancillary_crc_failures(skip_ancillary_crc_failures)
673 }
674
675 pub fn update(
681 &mut self,
682 mut buf: &[u8],
683 mut image_data: Option<&mut UnfilterBuf<'_>>,
684 ) -> Result<(usize, Decoded), DecodingError> {
685 if self.state.is_none() {
686 return Err(DecodingError::Parameter(
687 ParameterErrorKind::PolledAfterFatalError.into(),
688 ));
689 }
690
691 let len = buf.len();
692 while !buf.is_empty() {
693 let image_data = image_data.as_deref_mut();
694
695 match self.next_state(buf, image_data) {
696 Ok((bytes, Decoded::Nothing)) => buf = &buf[bytes..],
697 Ok((bytes, result)) => {
698 buf = &buf[bytes..];
699 return Ok((len - buf.len(), result));
700 }
701 Err(err) => {
702 debug_assert!(self.state.is_none());
703 return Err(err);
704 }
705 }
706 }
707 Ok((len - buf.len(), Decoded::Nothing))
708 }
709
710 fn next_state(
711 &mut self,
712 buf: &[u8],
713 image_data: Option<&mut UnfilterBuf<'_>>,
714 ) -> Result<(usize, Decoded), DecodingError> {
715 use self::State::*;
716
717 let state = self.state.take().unwrap();
719
720 match state {
721 U32 {
722 kind,
723 mut bytes,
724 mut accumulated_count,
725 } => {
726 debug_assert!(accumulated_count <= 4);
727 if accumulated_count == 0 && buf.len() >= 4 {
728 const CONSUMED_BYTES: usize = 4;
734 self.parse_u32(kind, &buf[0..4], image_data, CONSUMED_BYTES)
735 } else {
736 let remaining_count = 4 - accumulated_count;
737 let consumed_bytes = {
738 let available_count = min(remaining_count, buf.len());
739 bytes[accumulated_count..accumulated_count + available_count]
740 .copy_from_slice(&buf[0..available_count]);
741 accumulated_count += available_count;
742 available_count
743 };
744
745 if accumulated_count < 4 {
746 self.state = Some(U32 {
747 kind,
748 bytes,
749 accumulated_count,
750 });
751 Ok((consumed_bytes, Decoded::Nothing))
752 } else {
753 debug_assert_eq!(accumulated_count, 4);
754 self.parse_u32(kind, &bytes, image_data, consumed_bytes)
755 }
756 }
757 }
758 ReadChunkData(type_str) => {
759 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
760 if self.current_chunk.remaining == 0 {
761 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
762 Ok((0, Decoded::Nothing))
763 } else {
764 let ChunkState {
765 crc,
766 remaining,
767 raw_bytes,
768 type_: _,
769 action,
770 } = &mut self.current_chunk;
771
772 let buf_avail = raw_bytes.capacity() - raw_bytes.len();
773 let bytes_avail = min(buf.len(), buf_avail);
774 let n = min(*remaining, bytes_avail as u32);
775 let buf = &buf[..n as usize];
776
777 if !self.decode_options.ignore_crc {
778 crc.update(buf);
779 }
780
781 if *action == ChunkAction::Process {
782 if raw_bytes.len() == raw_bytes.capacity() {
783 if self.limits.bytes == 0 {
784 return Err(DecodingError::LimitsExceeded);
785 }
786
787 debug_assert!(raw_bytes.capacity() > 0);
789 let reserve_size = raw_bytes.capacity().min(self.limits.bytes);
790
791 self.limits.reserve_bytes(reserve_size)?;
792 raw_bytes.reserve_exact(reserve_size);
793 }
794 raw_bytes.extend_from_slice(buf);
795 }
796
797 *remaining -= n;
798 if *remaining == 0 {
799 debug_assert!(type_str != IDAT && type_str != chunk::fdAT);
800 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
801 } else {
802 self.state = Some(ReadChunkData(type_str));
803 }
804 Ok((n as usize, Decoded::Nothing))
805 }
806 }
807 ImageData(type_str) => {
808 debug_assert!(type_str == IDAT || type_str == chunk::fdAT);
809 let len = std::cmp::min(buf.len(), self.current_chunk.remaining as usize);
810 let buf = &buf[..len];
811
812 let consumed = if let Some(image_data) = image_data {
813 self.inflater.decompress(buf, image_data)?
814 } else {
815 len
816 };
817
818 if !self.decode_options.ignore_crc {
819 self.current_chunk.crc.update(&buf[..consumed]);
820 }
821
822 self.current_chunk.remaining -= consumed as u32;
823 if self.current_chunk.remaining == 0 {
824 self.state = Some(State::new_u32(U32ValueKind::Crc(type_str)));
825 } else {
826 self.state = Some(ImageData(type_str));
827 }
828 Ok((consumed, Decoded::ImageData))
829 }
830 }
831 }
832
833 fn parse_u32(
834 &mut self,
835 kind: U32ValueKind,
836 u32_be_bytes: &[u8],
837 image_data: Option<&mut UnfilterBuf<'_>>,
838 consumed_bytes: usize,
839 ) -> Result<(usize, Decoded), DecodingError> {
840 debug_assert_eq!(u32_be_bytes.len(), 4);
841 let bytes = u32_be_bytes.try_into().unwrap();
842 let val = u32::from_be_bytes(bytes);
843
844 match kind {
845 U32ValueKind::Signature1stU32 => {
846 if bytes == [137, 80, 78, 71] {
847 self.state = Some(State::new_u32(U32ValueKind::Signature2ndU32));
848 Ok((consumed_bytes, Decoded::Nothing))
849 } else {
850 Err(DecodingError::Format(
851 FormatErrorInner::InvalidSignature.into(),
852 ))
853 }
854 }
855 U32ValueKind::Signature2ndU32 => {
856 if bytes == [13, 10, 26, 10] {
857 self.state = Some(State::new_u32(U32ValueKind::Length));
858 Ok((consumed_bytes, Decoded::Nothing))
859 } else {
860 Err(DecodingError::Format(
861 FormatErrorInner::InvalidSignature.into(),
862 ))
863 }
864 }
865 U32ValueKind::Length => {
866 self.state = Some(State::new_u32(U32ValueKind::Type { length: val }));
867 Ok((consumed_bytes, Decoded::Nothing))
868 }
869 U32ValueKind::Type { length } => {
870 let type_str = ChunkType(bytes);
871 if self.info.is_none() && type_str != IHDR {
872 return Err(DecodingError::Format(
873 FormatErrorInner::ChunkBeforeIhdr { kind: type_str }.into(),
874 ));
875 }
876 if type_str != self.current_chunk.type_
877 && (self.current_chunk.type_ == IDAT || self.current_chunk.type_ == chunk::fdAT)
878 {
879 let finished = match image_data {
880 Some(image_data) => self.inflater.finish(image_data)?,
881 None => true,
882 };
883
884 self.state = Some(State::U32 {
888 kind,
889 bytes,
890 accumulated_count: 4 - consumed_bytes,
891 });
892
893 if finished {
894 self.current_chunk.type_ = type_str;
898 self.ready_for_idat_chunks = false;
899 self.ready_for_fdat_chunks = false;
900 return Ok((0, Decoded::ImageDataFlushed));
901 } else {
902 return Ok((0, Decoded::ImageData));
906 }
907 }
908
909 self.current_chunk.type_ = type_str;
910 if !self.decode_options.ignore_crc {
911 self.current_chunk.crc.reset();
912 self.current_chunk.crc.update(&type_str.0);
913 }
914 self.current_chunk.remaining = length;
915 self.current_chunk.raw_bytes.clear();
916
917 self.state = match type_str {
918 chunk::fdAT => {
919 if !self.ready_for_fdat_chunks {
920 return Err(DecodingError::Format(
921 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
922 kind: chunk::fdAT,
923 }
924 .into(),
925 ));
926 }
927 if length < 4 {
928 return Err(DecodingError::Format(
929 FormatErrorInner::FdatShorterThanFourBytes.into(),
930 ));
931 }
932 self.current_chunk.action = ChunkAction::Process;
933 Some(State::new_u32(U32ValueKind::ApngSequenceNumber))
934 }
935 IDAT => {
936 if !self.ready_for_idat_chunks {
937 return Err(DecodingError::Format(
938 FormatErrorInner::UnexpectedRestartOfDataChunkSequence {
939 kind: IDAT,
940 }
941 .into(),
942 ));
943 }
944 self.have_idat = true;
945 self.current_chunk.action = ChunkAction::Process;
946 Some(State::ImageData(type_str))
947 }
948 _ => Some(self.start_chunk(type_str, length)?),
949 };
950 Ok((consumed_bytes, Decoded::ChunkBegin(length, type_str)))
951 }
952 U32ValueKind::Crc(type_str) => {
953 let sum = if self.decode_options.ignore_crc {
957 val
958 } else {
959 self.current_chunk.crc.clone().finalize()
960 };
961
962 if val == sum || CHECKSUM_DISABLED {
963 match self.current_chunk.action {
964 ChunkAction::Process => {
965 debug_assert!(self.state.is_none());
968 let decoded = self.parse_chunk(type_str)?;
969
970 if type_str != IEND {
971 self.state = Some(State::new_u32(U32ValueKind::Length));
972 }
973 Ok((consumed_bytes, decoded))
974 }
975 ChunkAction::Skip => {
976 self.state = Some(State::new_u32(U32ValueKind::Length));
977 Ok((
978 consumed_bytes,
979 Decoded::SkippedAncillaryChunk(self.current_chunk.type_),
980 ))
981 }
982 ChunkAction::Reject => {
983 self.state = Some(State::new_u32(U32ValueKind::Length));
984 Ok((consumed_bytes, Decoded::BadAncillaryChunk(type_str)))
985 }
986 }
987 } else if self.decode_options.skip_ancillary_crc_failures
988 && !chunk::is_critical(type_str)
989 {
990 self.state = Some(State::new_u32(U32ValueKind::Length));
992 Ok((consumed_bytes, Decoded::BadAncillaryChunk(type_str)))
993 } else {
994 Err(DecodingError::Format(
995 FormatErrorInner::CrcMismatch {
996 crc_val: val,
997 crc_sum: sum,
998 chunk: type_str,
999 }
1000 .into(),
1001 ))
1002 }
1003 }
1004 U32ValueKind::ApngSequenceNumber => {
1005 debug_assert_eq!(self.current_chunk.type_, chunk::fdAT);
1006 let next_seq_no = val;
1007
1008 debug_assert!(self.current_chunk.remaining >= 4);
1010 self.current_chunk.remaining -= 4;
1011
1012 if let Some(seq_no) = self.current_seq_no {
1013 if next_seq_no != seq_no + 1 {
1014 return Err(DecodingError::Format(
1015 FormatErrorInner::ApngOrder {
1016 present: next_seq_no,
1017 expected: seq_no + 1,
1018 }
1019 .into(),
1020 ));
1021 }
1022 self.current_seq_no = Some(next_seq_no);
1023 } else {
1024 return Err(DecodingError::Format(FormatErrorInner::MissingFctl.into()));
1025 }
1026
1027 if !self.decode_options.ignore_crc {
1028 let data = next_seq_no.to_be_bytes();
1029 self.current_chunk.crc.update(&data);
1030 }
1031
1032 self.state = Some(State::ImageData(chunk::fdAT));
1033 Ok((consumed_bytes, Decoded::Nothing))
1034 }
1035 }
1036 }
1037
1038 fn start_chunk(&mut self, type_str: ChunkType, length: u32) -> Result<State, DecodingError> {
1039 let target_length = match type_str {
1040 IHDR => 13..=13,
1041 chunk::PLTE => 3..=768,
1042 chunk::IEND => 0..=0,
1043 chunk::sBIT => 1..=4,
1044 chunk::tRNS => 1..=256,
1045 chunk::pHYs => 9..=9,
1046 chunk::gAMA => 4..=4,
1047 chunk::acTL => 8..=8,
1048 chunk::fcTL => 26..=26,
1049 chunk::cHRM => 32..=32,
1050 chunk::sRGB => 1..=1,
1051 chunk::cICP => 4..=4,
1052 chunk::mDCV => 24..=24,
1053 chunk::cLLI => 8..=8,
1054 chunk::bKGD => 1..=6,
1055
1056 chunk::eXIf => 0..=u32::MAX >> 1, chunk::iCCP if !self.decode_options.ignore_iccp_chunk => 0..=u32::MAX >> 1,
1059 chunk::tEXt if !self.decode_options.ignore_text_chunk => 0..=u32::MAX >> 1,
1060 chunk::zTXt if !self.decode_options.ignore_text_chunk => 0..=u32::MAX >> 1,
1061 chunk::iTXt if !self.decode_options.ignore_text_chunk => 0..=u32::MAX >> 1,
1062
1063 chunk::IDAT | chunk::fdAT => unreachable!(),
1064
1065 _ if is_critical(type_str) => {
1066 return Err(DecodingError::Format(
1067 FormatErrorInner::UnrecognizedCriticalChunk { type_str }.into(),
1068 ));
1069 }
1070 _ => {
1071 self.current_chunk.action = ChunkAction::Skip;
1072 return Ok(State::ReadChunkData(type_str));
1073 }
1074 };
1075
1076 if !target_length.contains(&length) {
1077 match type_str {
1080 IHDR | chunk::PLTE | chunk::IEND | chunk::fcTL => {
1081 return Err(DecodingError::Format(
1082 FormatErrorInner::ChunkLengthWrong { kind: type_str }.into(),
1083 ));
1084 }
1085 _ => {
1086 self.current_chunk.action = ChunkAction::Reject;
1087 }
1088 }
1089 } else {
1090 self.current_chunk.action = ChunkAction::Process;
1091 }
1092
1093 Ok(State::ReadChunkData(type_str))
1094 }
1095
1096 fn parse_chunk(&mut self, type_str: ChunkType) -> Result<Decoded, DecodingError> {
1097 let mut parse_result = match type_str {
1098 IHDR => self.parse_ihdr(),
1100 chunk::PLTE => self.parse_plte(),
1101 chunk::IEND => Ok(()), chunk::IDAT => Ok(()),
1105 chunk::fdAT => Ok(()),
1106
1107 chunk::sBIT => self.parse_sbit(),
1109 chunk::tRNS => self.parse_trns(),
1110 chunk::pHYs => self.parse_phys(),
1111 chunk::gAMA => self.parse_gama(),
1112 chunk::acTL => self.parse_actl(),
1113 chunk::fcTL => self.parse_fctl(),
1114 chunk::cHRM => self.parse_chrm(),
1115 chunk::sRGB => self.parse_srgb(),
1116 chunk::cICP => self.parse_cicp(),
1117 chunk::mDCV => self.parse_mdcv(),
1118 chunk::cLLI => self.parse_clli(),
1119 chunk::bKGD => self.parse_bkgd(),
1120
1121 chunk::eXIf => self.parse_exif(),
1123 chunk::iCCP => self.parse_iccp(),
1124 chunk::tEXt => self.parse_text(),
1125 chunk::zTXt => self.parse_ztxt(),
1126 chunk::iTXt => self.parse_itxt(),
1127
1128 _ => unreachable!(
1130 "Unrecognized chunk {type_str:?} should have been caught in start_chunk"
1131 ),
1132 };
1133
1134 parse_result = parse_result.map_err(|e| {
1135 match e {
1136 DecodingError::IoError(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => {
1141 let fmt_err: FormatError =
1142 FormatErrorInner::ChunkLengthWrong { kind: type_str }.into();
1143 fmt_err.into()
1144 }
1145 e => e,
1146 }
1147 });
1148
1149 match parse_result {
1150 Ok(()) => Ok(Decoded::ChunkComplete(type_str)),
1151 Err(DecodingError::Format(_))
1152 if type_str != chunk::fcTL && !chunk::is_critical(type_str) =>
1153 {
1154 Ok(Decoded::BadAncillaryChunk(type_str))
1162 }
1163 Err(e) => Err(e),
1164 }
1165 }
1166
1167 fn parse_fctl(&mut self) -> Result<(), DecodingError> {
1168 let mut buf = &self.current_chunk.raw_bytes[..];
1169 let next_seq_no = buf.read_be()?;
1170
1171 self.current_seq_no = Some(if let Some(seq_no) = self.current_seq_no {
1173 if next_seq_no != seq_no + 1 {
1174 return Err(DecodingError::Format(
1175 FormatErrorInner::ApngOrder {
1176 expected: seq_no + 1,
1177 present: next_seq_no,
1178 }
1179 .into(),
1180 ));
1181 }
1182 next_seq_no
1183 } else {
1184 if next_seq_no != 0 {
1185 return Err(DecodingError::Format(
1186 FormatErrorInner::ApngOrder {
1187 expected: 0,
1188 present: next_seq_no,
1189 }
1190 .into(),
1191 ));
1192 }
1193 0
1194 });
1195 self.inflater.reset();
1196 self.ready_for_fdat_chunks = self.have_idat;
1197 let fc = FrameControl {
1198 sequence_number: next_seq_no,
1199 width: buf.read_be()?,
1200 height: buf.read_be()?,
1201 x_offset: buf.read_be()?,
1202 y_offset: buf.read_be()?,
1203 delay_num: buf.read_be()?,
1204 delay_den: buf.read_be()?,
1205 dispose_op: {
1206 let dispose_op = buf.read_be()?;
1207 match DisposeOp::from_u8(dispose_op) {
1208 Some(dispose_op) => dispose_op,
1209 None => {
1210 return Err(DecodingError::Format(
1211 FormatErrorInner::InvalidDisposeOp(dispose_op).into(),
1212 ))
1213 }
1214 }
1215 },
1216 blend_op: {
1217 let blend_op = buf.read_be()?;
1218 match BlendOp::from_u8(blend_op) {
1219 Some(blend_op) => blend_op,
1220 None => {
1221 return Err(DecodingError::Format(
1222 FormatErrorInner::InvalidBlendOp(blend_op).into(),
1223 ))
1224 }
1225 }
1226 },
1227 };
1228 self.info.as_ref().unwrap().validate(&fc)?;
1229 if !self.have_idat {
1230 self.info.as_ref().unwrap().validate_default_image(&fc)?;
1231 }
1232 self.info.as_mut().unwrap().frame_control = Some(fc);
1233 Ok(())
1234 }
1235
1236 fn parse_actl(&mut self) -> Result<(), DecodingError> {
1237 let info = self.info.as_mut().unwrap();
1238 if self.have_idat {
1239 Err(DecodingError::Format(
1240 FormatErrorInner::AfterIdat { kind: chunk::acTL }.into(),
1241 ))
1242 } else if info.animation_control.is_some() {
1243 Err(DecodingError::Format(
1244 FormatErrorInner::DuplicateChunk { kind: chunk::acTL }.into(),
1245 ))
1246 } else {
1247 let mut buf = &self.current_chunk.raw_bytes[..];
1248 let actl = AnimationControl {
1249 num_frames: buf.read_be()?,
1250 num_plays: buf.read_be()?,
1251 };
1252 if actl.num_frames == 0 {
1255 return Ok(());
1256 }
1257
1258 if actl.num_frames > 0x7FFFFFFF || actl.num_plays > 0x7FFFFFFF {
1263 return Ok(());
1264 }
1265
1266 info.animation_control = Some(actl);
1267 Ok(())
1268 }
1269 }
1270
1271 fn parse_plte(&mut self) -> Result<(), DecodingError> {
1272 let info = self.info.as_mut().unwrap();
1273 if info.palette.is_some() {
1274 Err(DecodingError::Format(
1276 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1277 ))
1278 } else {
1279 info.palette = Some(Cow::Owned(self.current_chunk.raw_bytes.clone()));
1280 Ok(())
1281 }
1282 }
1283
1284 fn parse_sbit(&mut self) -> Result<(), DecodingError> {
1285 let info = self.info.as_mut().unwrap();
1286 if info.palette.is_some() {
1287 return Err(DecodingError::Format(
1288 FormatErrorInner::AfterPlte { kind: chunk::sBIT }.into(),
1289 ));
1290 }
1291
1292 if self.have_idat {
1293 return Err(DecodingError::Format(
1294 FormatErrorInner::AfterIdat { kind: chunk::sBIT }.into(),
1295 ));
1296 }
1297
1298 if info.sbit.is_some() {
1299 return Err(DecodingError::Format(
1300 FormatErrorInner::DuplicateChunk { kind: chunk::sBIT }.into(),
1301 ));
1302 }
1303
1304 let (color_type, bit_depth) = { (info.color_type, info.bit_depth) };
1305 let sample_depth = if color_type == ColorType::Indexed {
1307 BitDepth::Eight
1308 } else {
1309 bit_depth
1310 };
1311 let vec = self.current_chunk.raw_bytes.clone();
1312 let len = vec.len();
1313
1314 let expected = match color_type {
1316 ColorType::Grayscale => 1,
1317 ColorType::Rgb | ColorType::Indexed => 3,
1318 ColorType::GrayscaleAlpha => 2,
1319 ColorType::Rgba => 4,
1320 };
1321
1322 if expected != len {
1324 return Err(DecodingError::Format(
1325 FormatErrorInner::InvalidSbitChunkSize {
1326 color_type,
1327 expected,
1328 len,
1329 }
1330 .into(),
1331 ));
1332 }
1333
1334 for sbit in &vec {
1335 if *sbit < 1 || *sbit > sample_depth as u8 {
1336 return Err(DecodingError::Format(
1337 FormatErrorInner::InvalidSbit {
1338 sample_depth,
1339 sbit: *sbit,
1340 }
1341 .into(),
1342 ));
1343 }
1344 }
1345 info.sbit = Some(Cow::Owned(vec));
1346 Ok(())
1347 }
1348
1349 fn parse_trns(&mut self) -> Result<(), DecodingError> {
1350 let info = self.info.as_mut().unwrap();
1351 if info.trns.is_some() {
1352 return Err(DecodingError::Format(
1353 FormatErrorInner::DuplicateChunk { kind: chunk::PLTE }.into(),
1354 ));
1355 }
1356 let (color_type, bit_depth) = { (info.color_type, info.bit_depth as u8) };
1357 let mut vec = self.current_chunk.raw_bytes.clone();
1358 let len = vec.len();
1359 match color_type {
1360 ColorType::Grayscale => {
1361 if len < 2 {
1362 return Err(DecodingError::Format(
1363 FormatErrorInner::ShortPalette { expected: 2, len }.into(),
1364 ));
1365 }
1366 if bit_depth < 16 {
1367 vec[0] = vec[1];
1368 vec.truncate(1);
1369 }
1370 info.trns = Some(Cow::Owned(vec));
1371 Ok(())
1372 }
1373 ColorType::Rgb => {
1374 if len < 6 {
1375 return Err(DecodingError::Format(
1376 FormatErrorInner::ShortPalette { expected: 6, len }.into(),
1377 ));
1378 }
1379 if bit_depth < 16 {
1380 vec[0] = vec[1];
1381 vec[1] = vec[3];
1382 vec[2] = vec[5];
1383 vec.truncate(3);
1384 }
1385 info.trns = Some(Cow::Owned(vec));
1386 Ok(())
1387 }
1388 ColorType::Indexed => {
1389 if info.palette.is_none() {
1392 return Err(DecodingError::Format(
1393 FormatErrorInner::BeforePlte { kind: chunk::tRNS }.into(),
1394 ));
1395 } else if self.have_idat {
1396 return Err(DecodingError::Format(
1397 FormatErrorInner::OutsidePlteIdat { kind: chunk::tRNS }.into(),
1398 ));
1399 }
1400
1401 info.trns = Some(Cow::Owned(vec));
1402 Ok(())
1403 }
1404 c => Err(DecodingError::Format(
1405 FormatErrorInner::ColorWithBadTrns(c).into(),
1406 )),
1407 }
1408 }
1409
1410 fn parse_phys(&mut self) -> Result<(), DecodingError> {
1411 let info = self.info.as_mut().unwrap();
1412 if self.have_idat {
1413 Err(DecodingError::Format(
1414 FormatErrorInner::AfterIdat { kind: chunk::pHYs }.into(),
1415 ))
1416 } else if info.pixel_dims.is_some() {
1417 Err(DecodingError::Format(
1418 FormatErrorInner::DuplicateChunk { kind: chunk::pHYs }.into(),
1419 ))
1420 } else {
1421 let mut buf = &self.current_chunk.raw_bytes[..];
1422 let xppu = buf.read_be()?;
1423 let yppu = buf.read_be()?;
1424 let unit = buf.read_be()?;
1425 let unit = match Unit::from_u8(unit) {
1426 Some(unit) => unit,
1427 None => {
1428 return Err(DecodingError::Format(
1429 FormatErrorInner::InvalidUnit(unit).into(),
1430 ))
1431 }
1432 };
1433 let pixel_dims = PixelDimensions { xppu, yppu, unit };
1434 info.pixel_dims = Some(pixel_dims);
1435 Ok(())
1436 }
1437 }
1438
1439 fn parse_chrm(&mut self) -> Result<(), DecodingError> {
1440 let info = self.info.as_mut().unwrap();
1441 if self.have_idat {
1442 Err(DecodingError::Format(
1443 FormatErrorInner::AfterIdat { kind: chunk::cHRM }.into(),
1444 ))
1445 } else if info.chrm_chunk.is_some() {
1446 Err(DecodingError::Format(
1447 FormatErrorInner::DuplicateChunk { kind: chunk::cHRM }.into(),
1448 ))
1449 } else {
1450 let mut buf = &self.current_chunk.raw_bytes[..];
1451 let white_x: u32 = buf.read_be()?;
1452 let white_y: u32 = buf.read_be()?;
1453 let red_x: u32 = buf.read_be()?;
1454 let red_y: u32 = buf.read_be()?;
1455 let green_x: u32 = buf.read_be()?;
1456 let green_y: u32 = buf.read_be()?;
1457 let blue_x: u32 = buf.read_be()?;
1458 let blue_y: u32 = buf.read_be()?;
1459
1460 let source_chromaticities = SourceChromaticities {
1461 white: (
1462 ScaledFloat::from_scaled(white_x),
1463 ScaledFloat::from_scaled(white_y),
1464 ),
1465 red: (
1466 ScaledFloat::from_scaled(red_x),
1467 ScaledFloat::from_scaled(red_y),
1468 ),
1469 green: (
1470 ScaledFloat::from_scaled(green_x),
1471 ScaledFloat::from_scaled(green_y),
1472 ),
1473 blue: (
1474 ScaledFloat::from_scaled(blue_x),
1475 ScaledFloat::from_scaled(blue_y),
1476 ),
1477 };
1478
1479 info.chrm_chunk = Some(source_chromaticities);
1480 Ok(())
1481 }
1482 }
1483
1484 fn parse_gama(&mut self) -> Result<(), DecodingError> {
1485 let info = self.info.as_mut().unwrap();
1486 if self.have_idat {
1487 Err(DecodingError::Format(
1488 FormatErrorInner::AfterIdat { kind: chunk::gAMA }.into(),
1489 ))
1490 } else if info.gama_chunk.is_some() {
1491 Err(DecodingError::Format(
1492 FormatErrorInner::DuplicateChunk { kind: chunk::gAMA }.into(),
1493 ))
1494 } else {
1495 let mut buf = &self.current_chunk.raw_bytes[..];
1496 let source_gamma: u32 = buf.read_be()?;
1497 if source_gamma == 0 {
1498 return Err(DecodingError::Format(
1499 FormatErrorInner::BadGammaValue.into(),
1500 ));
1501 }
1502
1503 let source_gamma = ScaledFloat::from_scaled(source_gamma);
1504 info.gama_chunk = Some(source_gamma);
1505 Ok(())
1506 }
1507 }
1508
1509 fn parse_srgb(&mut self) -> Result<(), DecodingError> {
1510 let info = self.info.as_mut().unwrap();
1511 if self.have_idat {
1512 Err(DecodingError::Format(
1513 FormatErrorInner::AfterIdat { kind: chunk::sRGB }.into(),
1514 ))
1515 } else if info.srgb.is_some() {
1516 Err(DecodingError::Format(
1517 FormatErrorInner::DuplicateChunk { kind: chunk::sRGB }.into(),
1518 ))
1519 } else {
1520 let mut buf = &self.current_chunk.raw_bytes[..];
1521 let raw: u8 = buf.read_be()?; let rendering_intent = crate::SrgbRenderingIntent::from_raw(raw).ok_or_else(|| {
1523 FormatError::from(FormatErrorInner::InvalidSrgbRenderingIntent(raw))
1524 })?;
1525
1526 info.srgb = Some(rendering_intent);
1528 Ok(())
1529 }
1530 }
1531
1532 fn parse_cicp(&mut self) -> Result<(), DecodingError> {
1533 let info = self.info.as_mut().unwrap();
1534
1535 if info.coding_independent_code_points.is_some() {
1537 return Err(DecodingError::Format(
1538 FormatErrorInner::DuplicateChunk { kind: chunk::cICP }.into(),
1539 ));
1540 } else if info.palette.is_some() {
1541 return Err(DecodingError::Format(
1542 FormatErrorInner::AfterPlte { kind: chunk::cICP }.into(),
1543 ));
1544 } else if self.have_idat {
1545 return Err(DecodingError::Format(
1546 FormatErrorInner::AfterIdat { kind: chunk::cICP }.into(),
1547 ));
1548 }
1549
1550 let mut buf = &*self.current_chunk.raw_bytes;
1551 let color_primaries: u8 = buf.read_be()?;
1552 let transfer_function: u8 = buf.read_be()?;
1553 let matrix_coefficients: u8 = buf.read_be()?;
1554 let is_video_full_range_image = {
1555 let flag: u8 = buf.read_be()?;
1556 match flag {
1557 0 => false,
1558 1 => true,
1559 _ => {
1560 return Err(DecodingError::IoError(
1561 std::io::ErrorKind::InvalidData.into(),
1562 ));
1563 }
1564 }
1565 };
1566
1567 if matrix_coefficients != 0 {
1570 return Err(DecodingError::IoError(
1571 std::io::ErrorKind::InvalidData.into(),
1572 ));
1573 }
1574
1575 if !buf.is_empty() {
1576 return Err(DecodingError::IoError(
1577 std::io::ErrorKind::InvalidData.into(),
1578 ));
1579 }
1580
1581 info.coding_independent_code_points = Some(CodingIndependentCodePoints {
1582 color_primaries,
1583 transfer_function,
1584 matrix_coefficients,
1585 is_video_full_range_image,
1586 });
1587
1588 Ok(())
1589 }
1590
1591 fn parse_mdcv(&mut self) -> Result<(), DecodingError> {
1592 let info = self.info.as_mut().unwrap();
1593
1594 if info.mastering_display_color_volume.is_some() {
1596 return Err(DecodingError::Format(
1597 FormatErrorInner::DuplicateChunk { kind: chunk::mDCV }.into(),
1598 ));
1599 } else if info.palette.is_some() {
1600 return Err(DecodingError::Format(
1601 FormatErrorInner::AfterPlte { kind: chunk::mDCV }.into(),
1602 ));
1603 } else if self.have_idat {
1604 return Err(DecodingError::Format(
1605 FormatErrorInner::AfterIdat { kind: chunk::mDCV }.into(),
1606 ));
1607 }
1608
1609 let mut buf = &*self.current_chunk.raw_bytes;
1610 let red_x: u16 = buf.read_be()?;
1611 let red_y: u16 = buf.read_be()?;
1612 let green_x: u16 = buf.read_be()?;
1613 let green_y: u16 = buf.read_be()?;
1614 let blue_x: u16 = buf.read_be()?;
1615 let blue_y: u16 = buf.read_be()?;
1616 let white_x: u16 = buf.read_be()?;
1617 let white_y: u16 = buf.read_be()?;
1618 fn scale(chunk: u16) -> ScaledFloat {
1619 ScaledFloat::from_scaled((chunk as u32) * 2)
1626 }
1627 let chromaticities = SourceChromaticities {
1628 white: (scale(white_x), scale(white_y)),
1629 red: (scale(red_x), scale(red_y)),
1630 green: (scale(green_x), scale(green_y)),
1631 blue: (scale(blue_x), scale(blue_y)),
1632 };
1633 let max_luminance: u32 = buf.read_be()?;
1634 let min_luminance: u32 = buf.read_be()?;
1635 if !buf.is_empty() {
1636 return Err(DecodingError::IoError(
1637 std::io::ErrorKind::InvalidData.into(),
1638 ));
1639 }
1640 info.mastering_display_color_volume = Some(MasteringDisplayColorVolume {
1641 chromaticities,
1642 max_luminance,
1643 min_luminance,
1644 });
1645
1646 Ok(())
1647 }
1648
1649 fn parse_clli(&mut self) -> Result<(), DecodingError> {
1650 let info = self.info.as_mut().unwrap();
1651 if info.content_light_level.is_some() {
1652 return Err(DecodingError::Format(
1653 FormatErrorInner::DuplicateChunk { kind: chunk::cLLI }.into(),
1654 ));
1655 }
1656
1657 let mut buf = &*self.current_chunk.raw_bytes;
1658 let max_content_light_level: u32 = buf.read_be()?;
1659 let max_frame_average_light_level: u32 = buf.read_be()?;
1660 if !buf.is_empty() {
1661 return Err(DecodingError::IoError(
1662 std::io::ErrorKind::InvalidData.into(),
1663 ));
1664 }
1665 info.content_light_level = Some(ContentLightLevelInfo {
1666 max_content_light_level,
1667 max_frame_average_light_level,
1668 });
1669
1670 Ok(())
1671 }
1672
1673 fn parse_exif(&mut self) -> Result<(), DecodingError> {
1674 let info = self.info.as_mut().unwrap();
1675 if info.exif_metadata.is_some() {
1676 return Err(DecodingError::Format(
1677 FormatErrorInner::DuplicateChunk { kind: chunk::eXIf }.into(),
1678 ));
1679 }
1680
1681 info.exif_metadata = Some(self.current_chunk.raw_bytes.clone().into());
1682 Ok(())
1683 }
1684
1685 fn parse_iccp(&mut self) -> Result<(), DecodingError> {
1686 if self.have_idat {
1687 Err(DecodingError::Format(
1688 FormatErrorInner::AfterIdat { kind: chunk::iCCP }.into(),
1689 ))
1690 } else if self.have_iccp {
1691 Err(DecodingError::Format(
1692 FormatErrorInner::DuplicateChunk { kind: chunk::iCCP }.into(),
1693 ))
1694 } else {
1695 self.have_iccp = true;
1696 let _ = self.parse_iccp_raw();
1697 Ok(())
1698 }
1699 }
1700
1701 fn parse_iccp_raw(&mut self) -> Result<(), DecodingError> {
1702 let info = self.info.as_mut().unwrap();
1703 let mut buf = &self.current_chunk.raw_bytes[..];
1704
1705 for len in 0..=80 {
1707 let raw: u8 = buf.read_be()?;
1708 if (raw == 0 && len == 0) || (raw != 0 && len == 80) {
1709 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1710 }
1711 if raw == 0 {
1712 break;
1713 }
1714 }
1715
1716 match buf.read_be()? {
1717 0u8 => (),
1719 n => {
1720 return Err(DecodingError::Format(
1721 FormatErrorInner::UnknownCompressionMethod(n).into(),
1722 ))
1723 }
1724 }
1725
1726 match fdeflate::decompress_to_vec_bounded(buf, self.limits.bytes) {
1727 Ok(profile) => {
1728 self.limits.reserve_bytes(profile.len())?;
1729 info.icc_profile = Some(Cow::Owned(profile));
1730 }
1731 Err(fdeflate::BoundedDecompressionError::DecompressionError { inner: err }) => {
1732 return Err(DecodingError::Format(
1733 FormatErrorInner::CorruptFlateStream { err }.into(),
1734 ))
1735 }
1736 Err(fdeflate::BoundedDecompressionError::OutputTooLarge { .. }) => {
1737 return Err(DecodingError::LimitsExceeded);
1738 }
1739 }
1740
1741 Ok(())
1742 }
1743
1744 fn parse_ihdr(&mut self) -> Result<(), DecodingError> {
1745 if self.info.is_some() {
1746 return Err(DecodingError::Format(
1747 FormatErrorInner::DuplicateChunk { kind: IHDR }.into(),
1748 ));
1749 }
1750 let mut buf = &self.current_chunk.raw_bytes[..];
1751 let width = buf.read_be()?;
1752 let height = buf.read_be()?;
1753 if width == 0 || height == 0 {
1754 return Err(DecodingError::Format(
1755 FormatErrorInner::InvalidDimensions.into(),
1756 ));
1757 }
1758 let bit_depth = buf.read_be()?;
1759 let bit_depth = match BitDepth::from_u8(bit_depth) {
1760 Some(bits) => bits,
1761 None => {
1762 return Err(DecodingError::Format(
1763 FormatErrorInner::InvalidBitDepth(bit_depth).into(),
1764 ))
1765 }
1766 };
1767 let color_type = buf.read_be()?;
1768 let color_type = match ColorType::from_u8(color_type) {
1769 Some(color_type) => {
1770 if color_type.is_combination_invalid(bit_depth) {
1771 return Err(DecodingError::Format(
1772 FormatErrorInner::InvalidColorBitDepth {
1773 color_type,
1774 bit_depth,
1775 }
1776 .into(),
1777 ));
1778 } else {
1779 color_type
1780 }
1781 }
1782 None => {
1783 return Err(DecodingError::Format(
1784 FormatErrorInner::InvalidColorType(color_type).into(),
1785 ))
1786 }
1787 };
1788 match buf.read_be()? {
1789 0u8 => (),
1791 n => {
1792 return Err(DecodingError::Format(
1793 FormatErrorInner::UnknownCompressionMethod(n).into(),
1794 ))
1795 }
1796 }
1797 match buf.read_be()? {
1798 0u8 => (),
1800 n => {
1801 return Err(DecodingError::Format(
1802 FormatErrorInner::UnknownFilterMethod(n).into(),
1803 ))
1804 }
1805 }
1806 let interlaced = match buf.read_be()? {
1807 0u8 => false,
1808 1 => true,
1809 n => {
1810 return Err(DecodingError::Format(
1811 FormatErrorInner::UnknownInterlaceMethod(n).into(),
1812 ))
1813 }
1814 };
1815
1816 self.info = Some(Info {
1817 width,
1818 height,
1819 bit_depth,
1820 color_type,
1821 interlaced,
1822 ..Default::default()
1823 });
1824
1825 Ok(())
1826 }
1827
1828 fn split_keyword(buf: &[u8]) -> Result<(&[u8], &[u8]), DecodingError> {
1829 let null_byte_index = buf
1830 .iter()
1831 .position(|&b| b == 0)
1832 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?;
1833
1834 if null_byte_index == 0 || null_byte_index > 79 {
1835 return Err(DecodingError::from(TextDecodingError::InvalidKeywordSize));
1836 }
1837
1838 Ok((&buf[..null_byte_index], &buf[null_byte_index + 1..]))
1839 }
1840
1841 fn parse_text(&mut self) -> Result<(), DecodingError> {
1842 let buf = &self.current_chunk.raw_bytes[..];
1843 self.limits.reserve_bytes(buf.len())?;
1844
1845 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1846
1847 self.info
1848 .as_mut()
1849 .unwrap()
1850 .uncompressed_latin1_text
1851 .push(TEXtChunk::decode(keyword_slice, value_slice).map_err(DecodingError::from)?);
1852
1853 Ok(())
1854 }
1855
1856 fn parse_ztxt(&mut self) -> Result<(), DecodingError> {
1857 let buf = &self.current_chunk.raw_bytes[..];
1858 self.limits.reserve_bytes(buf.len())?;
1859
1860 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1861
1862 let compression_method = *value_slice
1863 .first()
1864 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1865
1866 let text_slice = &value_slice[1..];
1867
1868 self.info.as_mut().unwrap().compressed_latin1_text.push(
1869 ZTXtChunk::decode(keyword_slice, compression_method, text_slice)
1870 .map_err(DecodingError::from)?,
1871 );
1872
1873 Ok(())
1874 }
1875
1876 fn parse_itxt(&mut self) -> Result<(), DecodingError> {
1877 let buf = &self.current_chunk.raw_bytes[..];
1878 self.limits.reserve_bytes(buf.len())?;
1879
1880 let (keyword_slice, value_slice) = Self::split_keyword(buf)?;
1881
1882 let compression_flag = *value_slice
1883 .first()
1884 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingCompressionFlag))?;
1885
1886 let compression_method = *value_slice
1887 .get(1)
1888 .ok_or_else(|| DecodingError::from(TextDecodingError::InvalidCompressionMethod))?;
1889
1890 let second_null_byte_index = value_slice[2..]
1891 .iter()
1892 .position(|&b| b == 0)
1893 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1894 + 2;
1895
1896 let language_tag_slice = &value_slice[2..second_null_byte_index];
1897
1898 let third_null_byte_index = value_slice[second_null_byte_index + 1..]
1899 .iter()
1900 .position(|&b| b == 0)
1901 .ok_or_else(|| DecodingError::from(TextDecodingError::MissingNullSeparator))?
1902 + (second_null_byte_index + 1);
1903
1904 let translated_keyword_slice =
1905 &value_slice[second_null_byte_index + 1..third_null_byte_index];
1906
1907 let text_slice = &value_slice[third_null_byte_index + 1..];
1908
1909 self.info.as_mut().unwrap().utf8_text.push(
1910 ITXtChunk::decode(
1911 keyword_slice,
1912 compression_flag,
1913 compression_method,
1914 language_tag_slice,
1915 translated_keyword_slice,
1916 text_slice,
1917 )
1918 .map_err(DecodingError::from)?,
1919 );
1920
1921 Ok(())
1922 }
1923
1924 fn parse_bkgd(&mut self) -> Result<(), DecodingError> {
1925 let info = self.info.as_mut().unwrap();
1926 if info.bkgd.is_some() {
1927 return Err(DecodingError::Format(
1929 FormatErrorInner::DuplicateChunk { kind: chunk::bKGD }.into(),
1930 ));
1931 } else if self.have_idat {
1932 return Err(DecodingError::Format(
1933 FormatErrorInner::AfterIdat { kind: chunk::bKGD }.into(),
1934 ));
1935 }
1936
1937 let expected = match info.color_type {
1938 ColorType::Indexed => {
1939 if info.palette.is_none() {
1940 return Err(DecodingError::IoError(
1941 std::io::ErrorKind::InvalidData.into(),
1942 ));
1943 };
1944 1
1945 }
1946 ColorType::Grayscale | ColorType::GrayscaleAlpha => 2,
1947 ColorType::Rgb | ColorType::Rgba => 6,
1948 };
1949 let vec = self.current_chunk.raw_bytes.clone();
1950 if vec.len() != expected {
1951 return Err(DecodingError::Format(
1952 FormatErrorInner::ChunkLengthWrong { kind: chunk::bKGD }.into(),
1953 ));
1954 }
1955
1956 info.bkgd = Some(Cow::Owned(vec));
1957 Ok(())
1958 }
1959}
1960
1961impl Info<'_> {
1962 fn validate_default_image(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1963 if fc.x_offset != 0
1972 || fc.y_offset != 0
1973 || fc.width != self.width
1974 || fc.height != self.height
1975 {
1976 return Err(DecodingError::Format(
1977 FormatErrorInner::BadSubFrameBounds {}.into(),
1978 ));
1979 }
1980 Ok(())
1981 }
1982
1983 fn validate(&self, fc: &FrameControl) -> Result<(), DecodingError> {
1984 if fc.width == 0 || fc.height == 0 {
1985 return Err(DecodingError::Format(
1986 FormatErrorInner::InvalidDimensions.into(),
1987 ));
1988 }
1989
1990 let in_x_bounds = Some(fc.width) <= self.width.checked_sub(fc.x_offset);
1992 let in_y_bounds = Some(fc.height) <= self.height.checked_sub(fc.y_offset);
1994
1995 if !in_x_bounds || !in_y_bounds {
1996 return Err(DecodingError::Format(
1997 FormatErrorInner::BadSubFrameBounds {}.into(),
1999 ));
2000 }
2001
2002 Ok(())
2003 }
2004}
2005
2006impl Default for StreamingDecoder {
2007 fn default() -> Self {
2008 Self::new()
2009 }
2010}
2011
2012#[cfg(test)]
2013mod tests {
2014 use super::ScaledFloat;
2015 use super::SourceChromaticities;
2016 use crate::test_utils::*;
2017 use crate::{Decoder, DecodingError, Reader, SrgbRenderingIntent, Unit};
2018 use approx::assert_relative_eq;
2019 use byteorder::WriteBytesExt;
2020 use std::borrow::Cow;
2021 use std::cell::RefCell;
2022
2023 use std::fs::File;
2024 use std::io::BufRead;
2025 use std::io::Cursor;
2026 use std::io::Seek;
2027 use std::io::{BufReader, ErrorKind, Read, Write};
2028 use std::rc::Rc;
2029
2030 #[test]
2031 fn image_gamma() -> Result<(), ()> {
2032 fn trial(path: &str, expected: Option<ScaledFloat>) {
2033 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
2034 let reader = decoder.read_info().unwrap();
2035 let actual: Option<ScaledFloat> = reader.info().gamma();
2036 assert!(actual == expected);
2037 }
2038 trial("tests/pngsuite/f00n0g08.png", None);
2039 trial("tests/pngsuite/f00n2c08.png", None);
2040 trial("tests/pngsuite/f01n0g08.png", None);
2041 trial("tests/pngsuite/f01n2c08.png", None);
2042 trial("tests/pngsuite/f02n0g08.png", None);
2043 trial("tests/pngsuite/f02n2c08.png", None);
2044 trial("tests/pngsuite/f03n0g08.png", None);
2045 trial("tests/pngsuite/f03n2c08.png", None);
2046 trial("tests/pngsuite/f04n0g08.png", None);
2047 trial("tests/pngsuite/f04n2c08.png", None);
2048 trial("tests/pngsuite/f99n0g04.png", None);
2049 trial("tests/pngsuite/tm3n3p02.png", None);
2050 trial("tests/pngsuite/g03n0g16.png", Some(ScaledFloat::new(0.35)));
2051 trial("tests/pngsuite/g03n2c08.png", Some(ScaledFloat::new(0.35)));
2052 trial("tests/pngsuite/g03n3p04.png", Some(ScaledFloat::new(0.35)));
2053 trial("tests/pngsuite/g04n0g16.png", Some(ScaledFloat::new(0.45)));
2054 trial("tests/pngsuite/g04n2c08.png", Some(ScaledFloat::new(0.45)));
2055 trial("tests/pngsuite/g04n3p04.png", Some(ScaledFloat::new(0.45)));
2056 trial("tests/pngsuite/g05n0g16.png", Some(ScaledFloat::new(0.55)));
2057 trial("tests/pngsuite/g05n2c08.png", Some(ScaledFloat::new(0.55)));
2058 trial("tests/pngsuite/g05n3p04.png", Some(ScaledFloat::new(0.55)));
2059 trial("tests/pngsuite/g07n0g16.png", Some(ScaledFloat::new(0.7)));
2060 trial("tests/pngsuite/g07n2c08.png", Some(ScaledFloat::new(0.7)));
2061 trial("tests/pngsuite/g07n3p04.png", Some(ScaledFloat::new(0.7)));
2062 trial("tests/pngsuite/g10n0g16.png", Some(ScaledFloat::new(1.0)));
2063 trial("tests/pngsuite/g10n2c08.png", Some(ScaledFloat::new(1.0)));
2064 trial("tests/pngsuite/g10n3p04.png", Some(ScaledFloat::new(1.0)));
2065 trial("tests/pngsuite/g25n0g16.png", Some(ScaledFloat::new(2.5)));
2066 trial("tests/pngsuite/g25n2c08.png", Some(ScaledFloat::new(2.5)));
2067 trial("tests/pngsuite/g25n3p04.png", Some(ScaledFloat::new(2.5)));
2068 Ok(())
2069 }
2070
2071 #[test]
2072 fn image_source_chromaticities() -> Result<(), ()> {
2073 fn trial(path: &str, expected: Option<SourceChromaticities>) {
2074 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
2075 let reader = decoder.read_info().unwrap();
2076 let actual: Option<SourceChromaticities> = reader.info().chromaticities();
2077 assert!(actual == expected);
2078 }
2079 trial(
2080 "tests/pngsuite/ccwn2c08.png",
2081 Some(SourceChromaticities::new(
2082 (0.3127, 0.3290),
2083 (0.64, 0.33),
2084 (0.30, 0.60),
2085 (0.15, 0.06),
2086 )),
2087 );
2088 trial(
2089 "tests/pngsuite/ccwn3p08.png",
2090 Some(SourceChromaticities::new(
2091 (0.3127, 0.3290),
2092 (0.64, 0.33),
2093 (0.30, 0.60),
2094 (0.15, 0.06),
2095 )),
2096 );
2097 trial("tests/pngsuite/basi0g01.png", None);
2098 trial("tests/pngsuite/basi0g02.png", None);
2099 trial("tests/pngsuite/basi0g04.png", None);
2100 trial("tests/pngsuite/basi0g08.png", None);
2101 trial("tests/pngsuite/basi0g16.png", None);
2102 trial("tests/pngsuite/basi2c08.png", None);
2103 trial("tests/pngsuite/basi2c16.png", None);
2104 trial("tests/pngsuite/basi3p01.png", None);
2105 trial("tests/pngsuite/basi3p02.png", None);
2106 trial("tests/pngsuite/basi3p04.png", None);
2107 trial("tests/pngsuite/basi3p08.png", None);
2108 trial("tests/pngsuite/basi4a08.png", None);
2109 trial("tests/pngsuite/basi4a16.png", None);
2110 trial("tests/pngsuite/basi6a08.png", None);
2111 trial("tests/pngsuite/basi6a16.png", None);
2112 trial("tests/pngsuite/basn0g01.png", None);
2113 trial("tests/pngsuite/basn0g02.png", None);
2114 trial("tests/pngsuite/basn0g04.png", None);
2115 trial("tests/pngsuite/basn0g08.png", None);
2116 trial("tests/pngsuite/basn0g16.png", None);
2117 trial("tests/pngsuite/basn2c08.png", None);
2118 trial("tests/pngsuite/basn2c16.png", None);
2119 trial("tests/pngsuite/basn3p01.png", None);
2120 trial("tests/pngsuite/basn3p02.png", None);
2121 trial("tests/pngsuite/basn3p04.png", None);
2122 trial("tests/pngsuite/basn3p08.png", None);
2123 trial("tests/pngsuite/basn4a08.png", None);
2124 trial("tests/pngsuite/basn4a16.png", None);
2125 trial("tests/pngsuite/basn6a08.png", None);
2126 trial("tests/pngsuite/basn6a16.png", None);
2127 trial("tests/pngsuite/bgai4a08.png", None);
2128 trial("tests/pngsuite/bgai4a16.png", None);
2129 trial("tests/pngsuite/bgan6a08.png", None);
2130 trial("tests/pngsuite/bgan6a16.png", None);
2131 trial("tests/pngsuite/bgbn4a08.png", None);
2132 trial("tests/pngsuite/bggn4a16.png", None);
2133 trial("tests/pngsuite/bgwn6a08.png", None);
2134 trial("tests/pngsuite/bgyn6a16.png", None);
2135 trial("tests/pngsuite/cdfn2c08.png", None);
2136 trial("tests/pngsuite/cdhn2c08.png", None);
2137 trial("tests/pngsuite/cdsn2c08.png", None);
2138 trial("tests/pngsuite/cdun2c08.png", None);
2139 trial("tests/pngsuite/ch1n3p04.png", None);
2140 trial("tests/pngsuite/ch2n3p08.png", None);
2141 trial("tests/pngsuite/cm0n0g04.png", None);
2142 trial("tests/pngsuite/cm7n0g04.png", None);
2143 trial("tests/pngsuite/cm9n0g04.png", None);
2144 trial("tests/pngsuite/cs3n2c16.png", None);
2145 trial("tests/pngsuite/cs3n3p08.png", None);
2146 trial("tests/pngsuite/cs5n2c08.png", None);
2147 trial("tests/pngsuite/cs5n3p08.png", None);
2148 trial("tests/pngsuite/cs8n2c08.png", None);
2149 trial("tests/pngsuite/cs8n3p08.png", None);
2150 trial("tests/pngsuite/ct0n0g04.png", None);
2151 trial("tests/pngsuite/ct1n0g04.png", None);
2152 trial("tests/pngsuite/cten0g04.png", None);
2153 trial("tests/pngsuite/ctfn0g04.png", None);
2154 trial("tests/pngsuite/ctgn0g04.png", None);
2155 trial("tests/pngsuite/cthn0g04.png", None);
2156 trial("tests/pngsuite/ctjn0g04.png", None);
2157 trial("tests/pngsuite/ctzn0g04.png", None);
2158 trial("tests/pngsuite/f00n0g08.png", None);
2159 trial("tests/pngsuite/f00n2c08.png", None);
2160 trial("tests/pngsuite/f01n0g08.png", None);
2161 trial("tests/pngsuite/f01n2c08.png", None);
2162 trial("tests/pngsuite/f02n0g08.png", None);
2163 trial("tests/pngsuite/f02n2c08.png", None);
2164 trial("tests/pngsuite/f03n0g08.png", None);
2165 trial("tests/pngsuite/f03n2c08.png", None);
2166 trial("tests/pngsuite/f04n0g08.png", None);
2167 trial("tests/pngsuite/f04n2c08.png", None);
2168 trial("tests/pngsuite/f99n0g04.png", None);
2169 trial("tests/pngsuite/g03n0g16.png", None);
2170 trial("tests/pngsuite/g03n2c08.png", None);
2171 trial("tests/pngsuite/g03n3p04.png", None);
2172 trial("tests/pngsuite/g04n0g16.png", None);
2173 trial("tests/pngsuite/g04n2c08.png", None);
2174 trial("tests/pngsuite/g04n3p04.png", None);
2175 trial("tests/pngsuite/g05n0g16.png", None);
2176 trial("tests/pngsuite/g05n2c08.png", None);
2177 trial("tests/pngsuite/g05n3p04.png", None);
2178 trial("tests/pngsuite/g07n0g16.png", None);
2179 trial("tests/pngsuite/g07n2c08.png", None);
2180 trial("tests/pngsuite/g07n3p04.png", None);
2181 trial("tests/pngsuite/g10n0g16.png", None);
2182 trial("tests/pngsuite/g10n2c08.png", None);
2183 trial("tests/pngsuite/g10n3p04.png", None);
2184 trial("tests/pngsuite/g25n0g16.png", None);
2185 trial("tests/pngsuite/g25n2c08.png", None);
2186 trial("tests/pngsuite/g25n3p04.png", None);
2187 trial("tests/pngsuite/oi1n0g16.png", None);
2188 trial("tests/pngsuite/oi1n2c16.png", None);
2189 trial("tests/pngsuite/oi2n0g16.png", None);
2190 trial("tests/pngsuite/oi2n2c16.png", None);
2191 trial("tests/pngsuite/oi4n0g16.png", None);
2192 trial("tests/pngsuite/oi4n2c16.png", None);
2193 trial("tests/pngsuite/oi9n0g16.png", None);
2194 trial("tests/pngsuite/oi9n2c16.png", None);
2195 trial("tests/pngsuite/PngSuite.png", None);
2196 trial("tests/pngsuite/pp0n2c16.png", None);
2197 trial("tests/pngsuite/pp0n6a08.png", None);
2198 trial("tests/pngsuite/ps1n0g08.png", None);
2199 trial("tests/pngsuite/ps1n2c16.png", None);
2200 trial("tests/pngsuite/ps2n0g08.png", None);
2201 trial("tests/pngsuite/ps2n2c16.png", None);
2202 trial("tests/pngsuite/s01i3p01.png", None);
2203 trial("tests/pngsuite/s01n3p01.png", None);
2204 trial("tests/pngsuite/s02i3p01.png", None);
2205 trial("tests/pngsuite/s02n3p01.png", None);
2206 trial("tests/pngsuite/s03i3p01.png", None);
2207 trial("tests/pngsuite/s03n3p01.png", None);
2208 trial("tests/pngsuite/s04i3p01.png", None);
2209 trial("tests/pngsuite/s04n3p01.png", None);
2210 trial("tests/pngsuite/s05i3p02.png", None);
2211 trial("tests/pngsuite/s05n3p02.png", None);
2212 trial("tests/pngsuite/s06i3p02.png", None);
2213 trial("tests/pngsuite/s06n3p02.png", None);
2214 trial("tests/pngsuite/s07i3p02.png", None);
2215 trial("tests/pngsuite/s07n3p02.png", None);
2216 trial("tests/pngsuite/s08i3p02.png", None);
2217 trial("tests/pngsuite/s08n3p02.png", None);
2218 trial("tests/pngsuite/s09i3p02.png", None);
2219 trial("tests/pngsuite/s09n3p02.png", None);
2220 trial("tests/pngsuite/s32i3p04.png", None);
2221 trial("tests/pngsuite/s32n3p04.png", None);
2222 trial("tests/pngsuite/s33i3p04.png", None);
2223 trial("tests/pngsuite/s33n3p04.png", None);
2224 trial("tests/pngsuite/s34i3p04.png", None);
2225 trial("tests/pngsuite/s34n3p04.png", None);
2226 trial("tests/pngsuite/s35i3p04.png", None);
2227 trial("tests/pngsuite/s35n3p04.png", None);
2228 trial("tests/pngsuite/s36i3p04.png", None);
2229 trial("tests/pngsuite/s36n3p04.png", None);
2230 trial("tests/pngsuite/s37i3p04.png", None);
2231 trial("tests/pngsuite/s37n3p04.png", None);
2232 trial("tests/pngsuite/s38i3p04.png", None);
2233 trial("tests/pngsuite/s38n3p04.png", None);
2234 trial("tests/pngsuite/s39i3p04.png", None);
2235 trial("tests/pngsuite/s39n3p04.png", None);
2236 trial("tests/pngsuite/s40i3p04.png", None);
2237 trial("tests/pngsuite/s40n3p04.png", None);
2238 trial("tests/pngsuite/tbbn0g04.png", None);
2239 trial("tests/pngsuite/tbbn2c16.png", None);
2240 trial("tests/pngsuite/tbbn3p08.png", None);
2241 trial("tests/pngsuite/tbgn2c16.png", None);
2242 trial("tests/pngsuite/tbgn3p08.png", None);
2243 trial("tests/pngsuite/tbrn2c08.png", None);
2244 trial("tests/pngsuite/tbwn0g16.png", None);
2245 trial("tests/pngsuite/tbwn3p08.png", None);
2246 trial("tests/pngsuite/tbyn3p08.png", None);
2247 trial("tests/pngsuite/tm3n3p02.png", None);
2248 trial("tests/pngsuite/tp0n0g08.png", None);
2249 trial("tests/pngsuite/tp0n2c08.png", None);
2250 trial("tests/pngsuite/tp0n3p08.png", None);
2251 trial("tests/pngsuite/tp1n3p08.png", None);
2252 trial("tests/pngsuite/z00n2c08.png", None);
2253 trial("tests/pngsuite/z03n2c08.png", None);
2254 trial("tests/pngsuite/z06n2c08.png", None);
2255 Ok(())
2256 }
2257
2258 #[test]
2259 fn image_source_sbit() {
2260 fn trial(path: &str, expected: Option<Cow<[u8]>>) {
2261 let decoder = crate::Decoder::new(BufReader::new(File::open(path).unwrap()));
2262 let reader = decoder.read_info().unwrap();
2263 let actual: Option<Cow<[u8]>> = reader.info().sbit.clone();
2264 assert!(actual == expected);
2265 }
2266
2267 trial("tests/sbit/g.png", Some(Cow::Owned(vec![5u8])));
2268 trial("tests/sbit/ga.png", Some(Cow::Owned(vec![5u8, 3u8])));
2269 trial(
2270 "tests/sbit/indexed.png",
2271 Some(Cow::Owned(vec![5u8, 6u8, 5u8])),
2272 );
2273 trial("tests/sbit/rgb.png", Some(Cow::Owned(vec![5u8, 6u8, 5u8])));
2274 trial(
2275 "tests/sbit/rgba.png",
2276 Some(Cow::Owned(vec![5u8, 6u8, 5u8, 8u8])),
2277 );
2278 }
2279
2280 #[test]
2283 fn test_two_iccp_chunks() {
2284 let decoder = crate::Decoder::new(BufReader::new(
2289 File::open("tests/bugfixes/issue#1825.png").unwrap(),
2290 ));
2291 let reader = decoder.read_info().unwrap();
2292 let icc_profile = reader.info().icc_profile.clone().unwrap().into_owned();
2293
2294 assert_eq!(4070462061, crc32fast::hash(&icc_profile));
2299 }
2300
2301 #[test]
2302 fn test_iccp_roundtrip() {
2303 let dummy_icc = b"I'm a profile";
2304
2305 let mut info = crate::Info::with_size(1, 1);
2306 info.icc_profile = Some(dummy_icc.into());
2307 let mut encoded_image = Vec::new();
2308 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2309 let mut enc = enc.write_header().unwrap();
2310 enc.write_image_data(&[0]).unwrap();
2311 enc.finish().unwrap();
2312
2313 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2314 let dec = dec.read_info().unwrap();
2315 assert_eq!(dummy_icc, &**dec.info().icc_profile.as_ref().unwrap());
2316 }
2317
2318 #[test]
2319 fn test_phys_roundtrip() {
2320 let mut info = crate::Info::with_size(1, 1);
2321 info.pixel_dims = Some(crate::PixelDimensions {
2322 xppu: 12,
2323 yppu: 34,
2324 unit: Unit::Meter,
2325 });
2326 let mut encoded_image = Vec::new();
2327 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2328 let mut enc = enc.write_header().unwrap();
2329 enc.write_image_data(&[0]).unwrap();
2330 enc.finish().unwrap();
2331
2332 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2333 let dec = dec.read_info().unwrap();
2334 let phys = dec.info().pixel_dims.as_ref().unwrap();
2335 assert_eq!(phys.xppu, 12);
2336 assert_eq!(phys.yppu, 34);
2337 assert_eq!(phys.unit, Unit::Meter);
2338 }
2339
2340 #[test]
2341 fn test_srgb_roundtrip() {
2342 let mut info = crate::Info::with_size(1, 1);
2343 info.srgb = Some(SrgbRenderingIntent::Saturation);
2344 let mut encoded_image = Vec::new();
2345 let enc = crate::Encoder::with_info(&mut encoded_image, info).unwrap();
2346 let mut enc = enc.write_header().unwrap();
2347 enc.write_image_data(&[0]).unwrap();
2348 enc.finish().unwrap();
2349
2350 let dec = crate::Decoder::new(Cursor::new(&encoded_image));
2351 let dec = dec.read_info().unwrap();
2352 assert_eq!(dec.info().srgb.unwrap(), SrgbRenderingIntent::Saturation);
2353 }
2354
2355 #[test]
2356 fn test_png_with_broken_iccp() {
2357 let decoder = crate::Decoder::new(BufReader::new(
2358 File::open("tests/iccp/broken_iccp.png").unwrap(),
2359 ));
2360 assert!(decoder.read_info().is_ok());
2361 let mut decoder = crate::Decoder::new(BufReader::new(
2362 File::open("tests/iccp/broken_iccp.png").unwrap(),
2363 ));
2364 decoder.set_ignore_iccp_chunk(true);
2365 assert!(decoder.read_info().is_ok());
2366 }
2367
2368 #[test]
2370 fn test_cicp_mdcv_and_clli_chunks() {
2371 let mut decoder = crate::Decoder::new(BufReader::new(
2372 File::open("tests/bugfixes/cicp_pq.png").unwrap(),
2373 ));
2374 decoder.ignore_checksums(true);
2375 let reader = decoder.read_info().unwrap();
2376 let info = reader.info();
2377
2378 let cicp = info.coding_independent_code_points.unwrap();
2379 assert_eq!(cicp.color_primaries, 9);
2380 assert_eq!(cicp.transfer_function, 16);
2381 assert_eq!(cicp.matrix_coefficients, 0);
2382 assert!(cicp.is_video_full_range_image);
2383
2384 let mdcv = info.mastering_display_color_volume.unwrap();
2385 assert_relative_eq!(mdcv.chromaticities.red.0.into_value(), 0.680);
2386 assert_relative_eq!(mdcv.chromaticities.red.1.into_value(), 0.320);
2387 assert_relative_eq!(mdcv.chromaticities.green.0.into_value(), 0.265);
2388 assert_relative_eq!(mdcv.chromaticities.green.1.into_value(), 0.690);
2389 assert_relative_eq!(mdcv.chromaticities.blue.0.into_value(), 0.150);
2390 assert_relative_eq!(mdcv.chromaticities.blue.1.into_value(), 0.060);
2391 assert_relative_eq!(mdcv.chromaticities.white.0.into_value(), 0.3127);
2392 assert_relative_eq!(mdcv.chromaticities.white.1.into_value(), 0.3290);
2393 assert_relative_eq!(mdcv.min_luminance as f32 / 10_000.0, 0.01);
2394 assert_relative_eq!(mdcv.max_luminance as f32 / 10_000.0, 5000.0);
2395
2396 let clli = info.content_light_level.unwrap();
2397 assert_relative_eq!(clli.max_content_light_level as f32 / 10_000.0, 4000.0);
2398 assert_relative_eq!(clli.max_frame_average_light_level as f32 / 10_000.0, 2627.0);
2399 }
2400
2401 #[test]
2403 fn test_exif_chunk() {
2404 let decoder = crate::Decoder::new(BufReader::new(
2405 File::open("tests/bugfixes/F-exif-chunk-early.png").unwrap(),
2406 ));
2407 let reader = decoder.read_info().unwrap();
2408 let info = reader.info();
2409 let exif = info.exif_metadata.as_ref().unwrap().as_ref();
2410 assert_eq!(exif.len(), 90);
2411 }
2412
2413 #[test]
2415 fn test_finishing_twice() {
2416 let mut png = Vec::new();
2417 write_noncompressed_png(&mut png, 16, 1024);
2418 let decoder = Decoder::new(Cursor::new(&png));
2419 let mut reader = decoder.read_info().unwrap();
2420
2421 reader.finish().unwrap();
2423
2424 let err = reader.finish().unwrap_err();
2426 assert!(matches!(&err, DecodingError::Parameter(_)));
2427 assert_eq!("End of image has been reached", format!("{err}"));
2428 }
2429
2430 fn write_actl(w: &mut impl Write, animation: &crate::AnimationControl) {
2433 let mut data = Vec::new();
2434 data.write_u32::<byteorder::BigEndian>(animation.num_frames)
2435 .unwrap();
2436 data.write_u32::<byteorder::BigEndian>(animation.num_plays)
2437 .unwrap();
2438 write_chunk(w, b"acTL", &data);
2439 }
2440
2441 fn write_fctl(w: &mut impl Write, frame: &crate::FrameControl) {
2444 let mut data = Vec::new();
2445 data.write_u32::<byteorder::BigEndian>(frame.sequence_number)
2446 .unwrap();
2447 data.write_u32::<byteorder::BigEndian>(frame.width).unwrap();
2448 data.write_u32::<byteorder::BigEndian>(frame.height)
2449 .unwrap();
2450 data.write_u32::<byteorder::BigEndian>(frame.x_offset)
2451 .unwrap();
2452 data.write_u32::<byteorder::BigEndian>(frame.y_offset)
2453 .unwrap();
2454 data.write_u16::<byteorder::BigEndian>(frame.delay_num)
2455 .unwrap();
2456 data.write_u16::<byteorder::BigEndian>(frame.delay_den)
2457 .unwrap();
2458 data.write_u8(frame.dispose_op as u8).unwrap();
2459 data.write_u8(frame.blend_op as u8).unwrap();
2460 write_chunk(w, b"fcTL", &data);
2461 }
2462
2463 fn write_fdat(w: &mut impl Write, sequence_number: u32, image_data: &[u8]) {
2466 let mut data = Vec::new();
2467 data.write_u32::<byteorder::BigEndian>(sequence_number)
2468 .unwrap();
2469 data.write_all(image_data).unwrap();
2470 write_chunk(w, b"fdAT", &data);
2471 }
2472
2473 fn write_fdat_prefix(w: &mut impl Write, num_frames: u32, width: u32) {
2478 write_png_sig(w);
2479 write_rgba8_ihdr_with_width(w, width);
2480 write_actl(
2481 w,
2482 &crate::AnimationControl {
2483 num_frames,
2484 num_plays: 0,
2485 },
2486 );
2487
2488 let mut fctl = crate::FrameControl {
2489 width,
2490 height: width,
2491 ..Default::default()
2492 };
2493 write_fctl(w, &fctl);
2494 write_rgba8_idats(w, width, 0x7fffffff);
2495
2496 fctl.sequence_number += 1;
2497 write_fctl(w, &fctl);
2498 }
2499
2500 #[test]
2501 fn test_fdat_chunk_without_idat() {
2502 let png = {
2503 let width = 1;
2504 let mut png = Vec::new();
2505 write_png_sig(&mut png);
2506 write_rgba8_ihdr_with_width(&mut png, width);
2507 let image_data = generate_rgba8_with_width_and_height(width, width);
2508 write_actl(
2509 &mut png,
2510 &crate::AnimationControl {
2511 num_frames: 2,
2512 num_plays: 1,
2513 },
2514 );
2515 let mut fctl = crate::FrameControl {
2516 sequence_number: 0,
2517 width,
2518 height: width,
2519 ..Default::default()
2520 };
2521 write_fctl(&mut png, &fctl);
2522 fctl.sequence_number = 1;
2523 write_fctl(&mut png, &fctl);
2524 write_fdat(&mut png, 1, &image_data[..]);
2525 write_iend(&mut png);
2526 png
2527 };
2528 let decoder = Decoder::new(Cursor::new(&png));
2529 let Err(err) = decoder.read_info() else {
2530 panic!("Expected an error")
2531 };
2532 assert!(matches!(&err, DecodingError::Format(_)));
2533 assert_eq!(
2534 "Unexpected restart of ChunkType { type: fdAT, \
2535 critical: false, \
2536 private: true, \
2537 reserved: false, \
2538 safecopy: false \
2539 } chunk sequence",
2540 format!("{err}"),
2541 );
2542 }
2543
2544 #[test]
2545 fn test_fdat_chunk_payload_length_0() {
2546 let mut png = Vec::new();
2547 write_fdat_prefix(&mut png, 2, 8);
2548 write_chunk(&mut png, b"fdAT", &[]);
2549
2550 let decoder = Decoder::new(Cursor::new(&png));
2551 let mut reader = decoder.read_info().unwrap();
2552 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2553 reader.next_frame(&mut buf).unwrap();
2554
2555 let err = reader.next_frame(&mut buf).unwrap_err();
2557 assert!(matches!(&err, DecodingError::Format(_)));
2558 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2559
2560 let err2 = reader.next_frame(&mut buf).unwrap_err();
2565 assert!(matches!(&err2, DecodingError::Parameter(_)));
2566 assert_eq!(
2567 "A fatal decoding error has been encounted earlier",
2568 format!("{err2}")
2569 );
2570 }
2571
2572 #[test]
2573 fn test_fdat_chunk_payload_length_3() {
2574 let mut png = Vec::new();
2575 write_fdat_prefix(&mut png, 2, 8);
2576 write_chunk(&mut png, b"fdAT", &[1, 0, 0]);
2577
2578 let decoder = Decoder::new(Cursor::new(&png));
2579 let mut reader = decoder.read_info().unwrap();
2580 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2581 reader.next_frame(&mut buf).unwrap();
2582
2583 let err = reader.next_frame(&mut buf).unwrap_err();
2585 assert!(matches!(&err, DecodingError::Format(_)));
2586 assert_eq!("fdAT chunk shorter than 4 bytes", format!("{err}"));
2587 }
2588
2589 #[test]
2590 fn test_frame_split_across_two_fdat_chunks() {
2591 let png = {
2606 let mut png = Vec::new();
2607 write_fdat_prefix(&mut png, 2, 8);
2608 let image_data = generate_rgba8_with_width_and_height(8, 8);
2609 write_fdat(&mut png, 2, &image_data[..30]);
2610 write_fdat(&mut png, 3, &image_data[30..]);
2611 write_iend(&mut png);
2612 png
2613 };
2614
2615 let decoder = Decoder::new(Cursor::new(&png));
2617 let mut reader = decoder.read_info().unwrap();
2618 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2619 let Some(animation_control) = reader.info().animation_control else {
2620 panic!("No acTL");
2621 };
2622 assert_eq!(animation_control.num_frames, 2);
2623
2624 let first_frame: Vec<u8>;
2626 {
2627 reader.next_frame(&mut buf).unwrap();
2628 first_frame = buf.clone();
2629
2630 let Some(frame_control) = reader.info().frame_control else {
2634 panic!("No fcTL (1st frame)");
2635 };
2636 assert_eq!(frame_control.sequence_number, 0);
2639 }
2640
2641 let second_frame: Vec<u8>;
2643 {
2644 reader.next_frame(&mut buf).unwrap();
2645 second_frame = buf.clone();
2646
2647 let Some(frame_control) = reader.info().frame_control else {
2649 panic!("No fcTL (2nd frame)");
2650 };
2651 assert_eq!(frame_control.sequence_number, 1);
2655 }
2656
2657 assert_eq!(first_frame, second_frame);
2658 }
2659
2660 #[test]
2661 fn test_idat_bigger_than_image_size_from_ihdr() {
2662 let png = {
2663 let mut png = Vec::new();
2664 write_png_sig(&mut png);
2665 write_rgba8_ihdr_with_width(&mut png, 8);
2666
2667 write_chunk(
2671 &mut png,
2672 b"IDAT",
2673 &generate_rgba8_with_width_and_height(8, 256),
2674 );
2675
2676 write_iend(&mut png);
2677 png
2678 };
2679 let decoder = Decoder::new(Cursor::new(&png));
2680 let mut reader = decoder.read_info().unwrap();
2681 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
2682
2683 reader.next_frame(&mut buf).unwrap();
2686 assert_eq!(3093270825, crc32fast::hash(&buf));
2687 }
2688
2689 #[test]
2690 fn test_only_idat_chunk_in_input_stream() {
2691 let png = {
2692 let mut png = Vec::new();
2693 write_png_sig(&mut png);
2694 write_chunk(&mut png, b"IDAT", &[]);
2695 png
2696 };
2697 let decoder = Decoder::new(Cursor::new(&png));
2698 let Err(err) = decoder.read_info() else {
2699 panic!("Expected an error")
2700 };
2701 assert!(matches!(&err, DecodingError::Format(_)));
2702 assert_eq!(
2703 "ChunkType { type: IDAT, \
2704 critical: true, \
2705 private: false, \
2706 reserved: false, \
2707 safecopy: false \
2708 } chunk appeared before IHDR chunk",
2709 format!("{err}"),
2710 );
2711 }
2712
2713 #[derive(Clone)]
2716 struct StreamingInput {
2717 full_input: Vec<u8>,
2718 state: Rc<RefCell<StreamingInputState>>,
2719 }
2720
2721 struct StreamingInputState {
2722 current_pos: usize,
2723 available_len: usize,
2724 }
2725
2726 impl StreamingInput {
2727 fn new(full_input: Vec<u8>) -> Self {
2728 Self {
2729 full_input,
2730 state: Rc::new(RefCell::new(StreamingInputState {
2731 current_pos: 0,
2732 available_len: 0,
2733 })),
2734 }
2735 }
2736
2737 fn with_noncompressed_png(width: u32, idat_size: usize) -> Self {
2738 let mut png = Vec::new();
2739 write_noncompressed_png(&mut png, width, idat_size);
2740 Self::new(png)
2741 }
2742
2743 fn expose_next_byte(&self) {
2744 let mut state = self.state.borrow_mut();
2745 assert!(state.available_len < self.full_input.len());
2746 state.available_len += 1;
2747 }
2748
2749 fn stream_input_until_reader_is_available(&self) -> Reader<StreamingInput> {
2750 loop {
2751 self.state.borrow_mut().current_pos = 0;
2752 match Decoder::new(self.clone()).read_info() {
2753 Ok(reader) => {
2754 break reader;
2755 }
2756 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2757 self.expose_next_byte();
2758 }
2759 _ => panic!("Unexpected error"),
2760 }
2761 }
2762 }
2763
2764 fn decode_full_input<F, R>(&self, f: F) -> R
2765 where
2766 F: FnOnce(Reader<Cursor<&[u8]>>) -> R,
2767 {
2768 let decoder = Decoder::new(Cursor::new(&*self.full_input));
2769 f(decoder.read_info().unwrap())
2770 }
2771 }
2772
2773 impl Read for StreamingInput {
2774 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
2775 let mut state = self.state.borrow_mut();
2776 let mut available_bytes = &self.full_input[state.current_pos..state.available_len];
2777 let number_of_read_bytes = available_bytes.read(buf)?;
2778 state.current_pos += number_of_read_bytes;
2779 assert!(state.current_pos <= state.available_len);
2780 Ok(number_of_read_bytes)
2781 }
2782 }
2783 impl BufRead for StreamingInput {
2784 fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
2785 let state = self.state.borrow();
2786 Ok(&self.full_input[state.current_pos..state.available_len])
2787 }
2788
2789 fn consume(&mut self, amt: usize) {
2790 let mut state = self.state.borrow_mut();
2791 state.current_pos += amt;
2792 assert!(state.current_pos <= state.available_len);
2793 }
2794 }
2795 impl Seek for StreamingInput {
2796 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
2797 let mut state = self.state.borrow_mut();
2798 state.current_pos = match pos {
2799 std::io::SeekFrom::Start(n) => n as usize,
2800 std::io::SeekFrom::End(n) => (self.full_input.len() as i64 + n) as usize,
2801 std::io::SeekFrom::Current(n) => (state.current_pos as i64 + n) as usize,
2802 } as usize;
2803 Ok(state.current_pos as u64)
2804 }
2805 fn stream_position(&mut self) -> std::io::Result<u64> {
2806 Ok(self.state.borrow().current_pos as u64)
2807 }
2808 }
2809
2810 #[test]
2812 fn test_streaming_input_and_decoding_via_next_frame() {
2813 const WIDTH: u32 = 16;
2814 const IDAT_SIZE: usize = 512;
2815 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2816
2817 let (whole_output_info, decoded_from_whole_input) =
2818 streaming_input.decode_full_input(|mut r| {
2819 let mut buf = vec![0; r.output_buffer_size().unwrap()];
2820 let output_info = r.next_frame(&mut buf).unwrap();
2821 (output_info, buf)
2822 });
2823
2824 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2825 let mut decoded_from_streaming_input = vec![0; png_reader.output_buffer_size().unwrap()];
2826 let streaming_output_info = loop {
2827 match png_reader.next_frame(decoded_from_streaming_input.as_mut_slice()) {
2828 Ok(output_info) => break output_info,
2829 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2830 streaming_input.expose_next_byte()
2831 }
2832 e => panic!("Unexpected error: {:?}", e),
2833 }
2834 };
2835 assert_eq!(whole_output_info, streaming_output_info);
2836 assert_eq!(
2837 crc32fast::hash(&decoded_from_whole_input),
2838 crc32fast::hash(&decoded_from_streaming_input)
2839 );
2840 }
2841
2842 #[test]
2844 fn test_streaming_input_and_decoding_via_next_row() {
2845 const WIDTH: u32 = 16;
2846 const IDAT_SIZE: usize = 512;
2847 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2848
2849 let decoded_from_whole_input = streaming_input.decode_full_input(|mut r| {
2850 let mut buf = vec![0; r.output_buffer_size().unwrap()];
2851 r.next_frame(&mut buf).unwrap();
2852 buf
2853 });
2854
2855 let mut png_reader = streaming_input.stream_input_until_reader_is_available();
2856 let mut decoded_from_streaming_input = Vec::new();
2857 loop {
2858 match png_reader.next_row() {
2859 Ok(None) => break,
2860 Ok(Some(row)) => decoded_from_streaming_input.extend_from_slice(row.data()),
2861 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2862 streaming_input.expose_next_byte()
2863 }
2864 e => panic!("Unexpected error: {:?}", e),
2865 }
2866 }
2867 assert_eq!(
2868 crc32fast::hash(&decoded_from_whole_input),
2869 crc32fast::hash(&decoded_from_streaming_input)
2870 );
2871 }
2872
2873 #[test]
2875 fn test_streaming_input_and_reading_header_info() {
2876 const WIDTH: u32 = 16;
2877 const IDAT_SIZE: usize = 512;
2878 let streaming_input = StreamingInput::with_noncompressed_png(WIDTH, IDAT_SIZE);
2879
2880 let info_from_whole_input = streaming_input.decode_full_input(|r| r.info().clone());
2881
2882 let mut decoder = Decoder::new(streaming_input.clone());
2883 let info_from_streaming_input = loop {
2884 match decoder.read_header_info() {
2885 Ok(info) => break info.clone(),
2886 Err(DecodingError::IoError(e)) if e.kind() == ErrorKind::UnexpectedEof => {
2887 streaming_input.expose_next_byte()
2888 }
2889 e => panic!("Unexpected error: {:?}", e),
2890 }
2891 };
2892
2893 assert_eq!(info_from_whole_input.width, info_from_streaming_input.width);
2894 assert_eq!(
2895 info_from_whole_input.height,
2896 info_from_streaming_input.height
2897 );
2898 assert_eq!(
2899 info_from_whole_input.bit_depth,
2900 info_from_streaming_input.bit_depth
2901 );
2902 assert_eq!(
2903 info_from_whole_input.color_type,
2904 info_from_streaming_input.color_type
2905 );
2906 assert_eq!(
2907 info_from_whole_input.interlaced,
2908 info_from_streaming_input.interlaced
2909 );
2910 }
2911
2912 fn create_reader_of_ihdr_idat() -> Reader<Cursor<Vec<u8>>> {
2915 let mut png = Vec::new();
2916 write_noncompressed_png(&mut png, 16, 1024);
2917 Decoder::new(Cursor::new(png)).read_info().unwrap()
2918 }
2919
2920 fn create_reader_of_ihdr_actl_fctl_idat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
2923 let width = 16;
2924 let mut fctl = crate::FrameControl {
2925 width,
2926 height: width,
2927 ..Default::default()
2928 };
2929
2930 let mut png = Vec::new();
2931 write_png_sig(&mut png);
2932 write_rgba8_ihdr_with_width(&mut png, width);
2933 write_actl(
2934 &mut png,
2935 &crate::AnimationControl {
2936 num_frames: 2,
2937 num_plays: 0,
2938 },
2939 );
2940 fctl.sequence_number = 0;
2941 write_fctl(&mut png, &fctl);
2942 let idat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height + 1);
2946 write_chunk(&mut png, b"IDAT", &idat_data);
2947
2948 let fdat_width = 10;
2949 fctl.sequence_number = 1;
2950 fctl.width = fdat_width;
2954 write_fctl(&mut png, &fctl);
2955 let fdat_data = generate_rgba8_with_width_and_height(fctl.width, fctl.height);
2956 write_fdat(&mut png, 2, &fdat_data);
2957 write_iend(&mut png);
2958
2959 Decoder::new(Cursor::new(png)).read_info().unwrap()
2960 }
2961
2962 fn create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat() -> Reader<Cursor<Vec<u8>>> {
2965 let width = 16;
2966 let frame_data = generate_rgba8_with_width_and_height(width, width);
2967 let mut fctl = crate::FrameControl {
2968 width,
2969 height: width,
2970 ..Default::default()
2971 };
2972
2973 let mut png = Vec::new();
2974 write_png_sig(&mut png);
2975 write_rgba8_ihdr_with_width(&mut png, width);
2976 write_actl(
2977 &mut png,
2978 &crate::AnimationControl {
2979 num_frames: 2,
2980 num_plays: 0,
2981 },
2982 );
2983 write_chunk(&mut png, b"IDAT", &frame_data);
2984 fctl.sequence_number = 0;
2985 write_fctl(&mut png, &fctl);
2986 write_fdat(&mut png, 1, &frame_data);
2987 fctl.sequence_number = 2;
2988 write_fctl(&mut png, &fctl);
2989 write_fdat(&mut png, 3, &frame_data);
2990 write_iend(&mut png);
2991
2992 Decoder::new(Cursor::new(png)).read_info().unwrap()
2993 }
2994
2995 fn get_fctl_sequence_number(reader: &Reader<impl BufRead + Seek>) -> u32 {
2996 reader
2997 .info()
2998 .frame_control
2999 .as_ref()
3000 .unwrap()
3001 .sequence_number
3002 }
3003
3004 #[test]
3007 fn test_next_frame_polling_after_end_non_animated() {
3008 let mut reader = create_reader_of_ihdr_idat();
3009 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3010 reader
3011 .next_frame(&mut buf)
3012 .expect("Expecting no error for IDAT frame");
3013
3014 let err = reader
3015 .next_frame(&mut buf)
3016 .expect_err("Main test - expecting error");
3017 assert!(
3018 matches!(&err, DecodingError::Parameter(_)),
3019 "Unexpected kind of error: {:?}",
3020 &err,
3021 );
3022 }
3023
3024 #[test]
3027 fn test_next_frame_info_polling_after_end_non_animated() {
3028 let mut reader = create_reader_of_ihdr_idat();
3029
3030 let err = reader
3031 .next_frame_info()
3032 .expect_err("Main test - expecting error");
3033 assert!(
3034 matches!(&err, DecodingError::Parameter(_)),
3035 "Unexpected kind of error: {:?}",
3036 &err,
3037 );
3038 }
3039
3040 #[test]
3044 fn test_next_frame_polling_after_end_idat_part_of_animation() {
3045 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
3046 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3047
3048 assert_eq!(get_fctl_sequence_number(&reader), 0);
3049 reader
3050 .next_frame(&mut buf)
3051 .expect("Expecting no error for IDAT frame");
3052
3053 assert_eq!(get_fctl_sequence_number(&reader), 0);
3055
3056 reader
3057 .next_frame(&mut buf)
3058 .expect("Expecting no error for fdAT frame");
3059 assert_eq!(get_fctl_sequence_number(&reader), 1);
3060
3061 let err = reader
3062 .next_frame(&mut buf)
3063 .expect_err("Main test - expecting error");
3064 assert!(
3065 matches!(&err, DecodingError::Parameter(_)),
3066 "Unexpected kind of error: {:?}",
3067 &err,
3068 );
3069 }
3070
3071 #[test]
3075 fn test_next_frame_polling_after_end_idat_not_part_of_animation() {
3076 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
3077 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3078
3079 assert!(reader.info().frame_control.is_none());
3080 reader
3081 .next_frame(&mut buf)
3082 .expect("Expecting no error for IDAT frame");
3083
3084 assert!(reader.info().frame_control.is_none());
3086
3087 reader
3088 .next_frame(&mut buf)
3089 .expect("Expecting no error for 1st fdAT frame");
3090 assert_eq!(get_fctl_sequence_number(&reader), 0);
3091
3092 reader
3093 .next_frame(&mut buf)
3094 .expect("Expecting no error for 2nd fdAT frame");
3095 assert_eq!(get_fctl_sequence_number(&reader), 2);
3096
3097 let err = reader
3098 .next_frame(&mut buf)
3099 .expect_err("Main test - expecting error");
3100 assert!(
3101 matches!(&err, DecodingError::Parameter(_)),
3102 "Unexpected kind of error: {:?}",
3103 &err,
3104 );
3105 }
3106
3107 #[test]
3110 fn test_row_by_row_then_next_frame() {
3111 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
3112 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3113
3114 assert_eq!(get_fctl_sequence_number(&reader), 0);
3115 while let Some(_) = reader.next_row().unwrap() {}
3116 assert_eq!(get_fctl_sequence_number(&reader), 0);
3117
3118 buf.fill(0x0f);
3119 reader
3120 .next_frame(&mut buf)
3121 .expect("Expecting no error from next_frame call");
3122
3123 assert_eq!(get_fctl_sequence_number(&reader), 1);
3125 assert!(buf.iter().any(|byte| *byte != 0x0f));
3126 }
3127
3128 #[test]
3132 fn test_row_by_row_of_two_frames() {
3133 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
3134
3135 let mut rows_of_frame1 = 0;
3136 assert_eq!(get_fctl_sequence_number(&reader), 0);
3137 while let Some(_) = reader.next_row().unwrap() {
3138 rows_of_frame1 += 1;
3139 }
3140 assert_eq!(rows_of_frame1, 16);
3141 assert_eq!(get_fctl_sequence_number(&reader), 0);
3142
3143 let mut rows_of_frame2 = 0;
3144 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
3145 assert_eq!(get_fctl_sequence_number(&reader), 1);
3146 while let Some(_) = reader.next_row().unwrap() {
3147 rows_of_frame2 += 1;
3148 }
3149 assert_eq!(rows_of_frame2, 16);
3150 assert_eq!(get_fctl_sequence_number(&reader), 1);
3151
3152 let err = reader
3153 .next_frame_info()
3154 .expect_err("No more frames - expecting error");
3155 assert!(
3156 matches!(&err, DecodingError::Parameter(_)),
3157 "Unexpected kind of error: {:?}",
3158 &err,
3159 );
3160 }
3161
3162 #[test]
3168 fn test_next_frame_info_after_next_frame() {
3169 let mut reader = create_reader_of_ihdr_actl_fctl_idat_fctl_fdat();
3170 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3171
3172 assert_eq!(get_fctl_sequence_number(&reader), 0);
3173 reader
3174 .next_frame(&mut buf)
3175 .expect("Expecting no error for IDAT frame");
3176
3177 assert_eq!(get_fctl_sequence_number(&reader), 0);
3179
3180 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 1);
3182 assert_eq!(get_fctl_sequence_number(&reader), 1);
3183
3184 reader
3185 .next_frame(&mut buf)
3186 .expect("Expecting no error for fdAT frame");
3187 assert_eq!(get_fctl_sequence_number(&reader), 1);
3188
3189 let err = reader
3190 .next_frame_info()
3191 .expect_err("Main test - expecting error");
3192 assert!(
3193 matches!(&err, DecodingError::Parameter(_)),
3194 "Unexpected kind of error: {:?}",
3195 &err,
3196 );
3197 }
3198
3199 #[test]
3202 fn test_next_frame_info_to_skip_first_frame() {
3203 let mut reader = create_reader_of_ihdr_actl_idat_fctl_fdat_fctl_fdat();
3204 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3205
3206 assert!(reader.info().frame_control.is_none());
3209
3210 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 0);
3213 assert_eq!(get_fctl_sequence_number(&reader), 0);
3214 reader
3215 .next_frame(&mut buf)
3216 .expect("Expecting no error for 1st fdAT frame");
3217 assert_eq!(get_fctl_sequence_number(&reader), 0);
3218
3219 assert_eq!(reader.next_frame_info().unwrap().sequence_number, 2);
3221 reader
3222 .next_frame(&mut buf)
3223 .expect("Expecting no error for 2nd fdAT frame");
3224 assert_eq!(get_fctl_sequence_number(&reader), 2);
3225
3226 let err = reader
3227 .next_frame_info()
3228 .expect_err("Main test - expecting error");
3229 assert!(
3230 matches!(&err, DecodingError::Parameter(_)),
3231 "Unexpected kind of error: {:?}",
3232 &err,
3233 );
3234 }
3235
3236 #[test]
3237 fn test_incorrect_trns_chunk_is_ignored() {
3238 let png = {
3239 let mut png = Vec::new();
3240 write_png_sig(&mut png);
3241 write_rgba8_ihdr_with_width(&mut png, 8);
3242 write_chunk(&mut png, b"tRNS", &[12, 34, 56]);
3243 write_chunk(
3244 &mut png,
3245 b"IDAT",
3246 &generate_rgba8_with_width_and_height(8, 8),
3247 );
3248 write_iend(&mut png);
3249 png
3250 };
3251 let decoder = Decoder::new(Cursor::new(&png));
3252 let mut reader = decoder.read_info().unwrap();
3253 let mut buf = vec![0; reader.output_buffer_size().unwrap()];
3254 assert!(reader.info().trns.is_none());
3255 reader.next_frame(&mut buf).unwrap();
3256 assert_eq!(3093270825, crc32fast::hash(&buf));
3257 assert!(reader.info().trns.is_none());
3258 }
3259
3260 #[test]
3262 fn test_actl_num_frames_zero() {
3263 let width = 16;
3264 let frame_data = generate_rgba8_with_width_and_height(width, width);
3265
3266 let mut png = Vec::new();
3267 write_png_sig(&mut png);
3268 write_rgba8_ihdr_with_width(&mut png, width);
3269 write_actl(
3270 &mut png,
3271 &crate::AnimationControl {
3272 num_frames: 0, num_plays: 0,
3274 },
3275 );
3276 write_fctl(
3282 &mut png,
3283 &crate::FrameControl {
3284 width,
3285 height: width,
3286 ..Default::default()
3287 },
3288 );
3289 write_chunk(&mut png, b"IDAT", &frame_data);
3290 write_iend(&mut png);
3291
3292 let mut reader = Decoder::new(Cursor::new(png)).read_info().unwrap();
3293
3294 while let Some(_row) = reader.next_interlaced_row().unwrap() {}
3300 }
3301
3302 #[test]
3303 fn test_small_fctl() {
3304 const FCTL_SIZE: u32 = 30;
3305 const IHDR_SIZE: u32 = 50;
3306 let mut png = Vec::new();
3307 write_png_sig(&mut png);
3308 write_rgba8_ihdr_with_width(&mut png, IHDR_SIZE);
3309 write_actl(
3310 &mut png,
3311 &crate::AnimationControl {
3312 num_frames: 1,
3313 num_plays: 1,
3314 },
3315 );
3316 write_fctl(
3317 &mut png,
3318 &crate::FrameControl {
3319 width: FCTL_SIZE,
3320 height: FCTL_SIZE,
3321 x_offset: 10,
3322 y_offset: 10,
3323 sequence_number: 0,
3324 ..Default::default()
3325 },
3326 );
3327 write_chunk(
3328 &mut png,
3329 b"IDAT",
3330 &generate_rgba8_with_width_and_height(IHDR_SIZE, IHDR_SIZE),
3331 );
3332 write_iend(&mut png);
3333
3334 let reader = Decoder::new(Cursor::new(png)).read_info();
3335 let err = reader.err().unwrap();
3336 assert!(matches!(&err, DecodingError::Format(_)));
3337 assert_eq!("Sub frame is out-of-bounds.", format!("{err}"));
3338 }
3339
3340 #[test]
3341 fn test_invalid_text_chunk() {
3342 let invalid_text_chunk = vec![b'A'; 100];
3346
3347 const SIZE: u32 = 20;
3348 let mut png = Vec::new();
3349 write_png_sig(&mut png);
3350 write_rgba8_ihdr_with_width(&mut png, SIZE);
3351 write_chunk(&mut png, b"tEXt", invalid_text_chunk.as_slice());
3352 write_chunk(
3353 &mut png,
3354 b"IDAT",
3355 &generate_rgba8_with_width_and_height(SIZE, SIZE),
3356 );
3357 write_iend(&mut png);
3358
3359 let reader = Decoder::new(Cursor::new(png)).read_info().unwrap();
3360 let info = reader.info();
3361 assert_eq!(info.width, SIZE);
3362 assert_eq!(info.uncompressed_latin1_text.len(), 0);
3363 }
3364
3365 #[test]
3367 fn test_duplicate_actl_chunk() {
3368 let width = 16;
3369 let frame_data = generate_rgba8_with_width_and_height(width, width);
3370
3371 let mut png = Vec::new();
3372 write_png_sig(&mut png);
3373 write_rgba8_ihdr_with_width(&mut png, width);
3374 write_actl(
3375 &mut png,
3376 &crate::AnimationControl {
3377 num_frames: 2,
3378 num_plays: 123,
3379 },
3380 );
3381 write_actl(
3382 &mut png,
3383 &crate::AnimationControl {
3384 num_frames: 1, num_plays: 456,
3386 },
3387 );
3388 write_chunk(&mut png, b"IDAT", &frame_data);
3389 write_iend(&mut png);
3390
3391 let reader = Decoder::new(Cursor::new(png)).read_info().unwrap();
3392 let Some(actl) = reader.info().animation_control.as_ref() else {
3393 panic!("No `animation_control`?")
3394 };
3395 assert_eq!(actl.num_frames, 2);
3396 assert_eq!(actl.num_plays, 123);
3397 }
3398}