@@ -349,6 +349,10 @@ where
349349 ifd_offsets : Vec < IfdPointer > ,
350350 /// Map from the ifd into the `ifd_offsets` ordered list.
351351 seen_ifds : cycles:: IfdCycles ,
352+ /// The directory, if we have not yet read it as an image.
353+ /// This is prioritized _over_ the image. Hence it must _not_ be set if we are currently
354+ /// reading a true image IFD that is instead stored in the `image` attribute.
355+ non_image_ifd : Option < Directory > ,
352356 image : Image ,
353357}
354358
@@ -624,6 +628,7 @@ impl<R: Read + Seek> Decoder<R> {
624628 chunk_offsets : Vec :: new ( ) ,
625629 chunk_bytes : Vec :: new ( ) ,
626630 } ,
631+ non_image_ifd : None ,
627632 } ;
628633 decoder. next_image ( ) ?;
629634 Ok ( decoder)
@@ -654,6 +659,7 @@ impl<R: Read + Seek> Decoder<R> {
654659 /// Loads the IFD at the specified index in the list, if one exists
655660 pub fn seek_to_image ( & mut self , ifd_index : usize ) -> TiffResult < ( ) > {
656661 let ifd = self . seek_to_directory ( ifd_index) ?;
662+ self . non_image_ifd = None ;
657663 self . image = Image :: from_reader ( & mut self . value_reader , ifd) ?;
658664 Ok ( ( ) )
659665 }
@@ -699,6 +705,7 @@ impl<R: Read + Seek> Decoder<R> {
699705 /// recovered by calling [`Self::restart_at_image`] with a valid offset and a successful seek.
700706 pub fn restart_at_image ( & mut self , offset : IfdPointer ) -> TiffResult < ( ) > {
701707 let ifd = self . restart_at_offset ( offset) ?;
708+ self . non_image_ifd = None ;
702709 self . image = Image :: from_reader ( & mut self . value_reader , ifd) ?;
703710 Ok ( ( ) )
704711 }
@@ -709,8 +716,10 @@ impl<R: Read + Seek> Decoder<R> {
709716 /// interpret the directory in the sequence as an image. Instead, it may be used to read a
710717 /// sequence of auxiliary IFDs that are not necessarily images. For instance, a directory
711718 /// referred to in the SubIfd tag may be a thumbnail
712- pub fn restart_at_directory ( & mut self , offset : IfdPointer ) -> TiffResult < Directory > {
713- self . restart_at_offset ( offset)
719+ pub fn restart_at_directory ( & mut self , offset : IfdPointer ) -> TiffResult < ( ) > {
720+ let ifd = self . restart_at_offset ( offset) ?;
721+ self . non_image_ifd = Some ( ifd) ;
722+ Ok ( ( ) )
714723 }
715724
716725 fn restart_at_offset ( & mut self , offset : IfdPointer ) -> TiffResult < Directory > {
@@ -726,6 +735,7 @@ impl<R: Read + Seek> Decoder<R> {
726735 fn next_ifd ( & mut self ) -> TiffResult < Directory > {
727736 let Some ( next_ifd) = self . next_ifd . take ( ) else {
728737 self . current_ifd = None ;
738+ self . non_image_ifd = None ;
729739
730740 return Err ( TiffError :: FormatError (
731741 TiffFormatError :: ImageFileDirectoryNotFound ,
@@ -753,6 +763,7 @@ impl<R: Read + Seek> Decoder<R> {
753763 /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
754764 pub fn next_image ( & mut self ) -> TiffResult < ( ) > {
755765 let ifd = self . next_ifd ( ) ?;
766+ self . non_image_ifd = None ;
756767 self . image = Image :: from_reader ( & mut self . value_reader , ifd) ?;
757768 Ok ( ( ) )
758769 }
@@ -761,8 +772,10 @@ impl<R: Read + Seek> Decoder<R> {
761772 ///
762773 /// If there is no further image in the TIFF file a format error is returned. To determine
763774 /// whether there are more images call `TIFFDecoder::more_directories` instead.
764- pub fn next_directory ( & mut self ) -> TiffResult < Directory > {
765- self . next_ifd ( )
775+ pub fn next_directory ( & mut self ) -> TiffResult < ( ) > {
776+ let ifd = self . next_ifd ( ) ?;
777+ self . non_image_ifd = Some ( ifd) ;
778+ Ok ( ( ) )
766779 }
767780
768781 /// Interpret the current directory as an image.
@@ -775,8 +788,15 @@ impl<R: Read + Seek> Decoder<R> {
775788 TiffFormatError :: ImageFileDirectoryNotFound ,
776789 ) ) ?;
777790
778- let ifd = self . read_directory ( current_ifd) ?;
779- self . image = Image :: from_reader ( & mut self . value_reader , ifd) ?;
791+ if let Some ( ifd) = & self . non_image_ifd {
792+ self . image = Image :: from_ref ( & mut self . value_reader , ifd) ?;
793+ // Definitely sets an IFD but this works without unwraps.
794+ self . image . ifd = self . non_image_ifd . take ( ) ;
795+ } else {
796+ // Probably re-reading an image but that's fine.
797+ let ifd = self . read_directory ( current_ifd) ?;
798+ self . image = Image :: from_reader ( & mut self . value_reader , ifd) ?;
799+ }
780800
781801 Ok ( ( ) )
782802 }
@@ -1283,11 +1303,22 @@ impl<R: Read + Seek> Decoder<R> {
12831303 }
12841304
12851305 /// Get the IFD decoder for our current image IFD.
1286- fn image_ifd ( & mut self ) -> IfdDecoder < ' _ > {
1306+ fn current_directory_ifd ( & mut self ) -> IfdDecoder < ' _ > {
1307+ // Special fallback. We do not want to error handle not having read a current directory, in
1308+ // particular as the behavior having a directory without tags will produce these errors
1309+ // anyways (most likely). Note that an empty directory is invalid in a TIFF.
1310+ static NO_IFD : Directory = Directory :: empty ( ) ;
1311+
1312+ let ifd = self
1313+ . non_image_ifd
1314+ . as_ref ( )
1315+ . or_else ( || self . image . ifd . as_ref ( ) )
1316+ . unwrap_or ( & NO_IFD ) ;
1317+
12871318 IfdDecoder {
12881319 inner : tag_reader:: TagReader {
12891320 decoder : & mut self . value_reader ,
1290- ifd : self . image . ifd . as_ref ( ) . unwrap ( ) ,
1321+ ifd,
12911322 } ,
12921323 }
12931324 }
@@ -1328,25 +1359,25 @@ impl<R: Read + Seek> Decoder<R> {
13281359 /// Tries to retrieve a tag from the current image directory.
13291360 /// Return `Ok(None)` if the tag is not present.
13301361 pub fn find_tag ( & mut self , tag : Tag ) -> TiffResult < Option < ifd:: Value > > {
1331- self . image_ifd ( ) . find_tag ( tag)
1362+ self . current_directory_ifd ( ) . find_tag ( tag)
13321363 }
13331364
13341365 /// Tries to retrieve a tag in the current image directory and convert it to the desired
13351366 /// unsigned type.
13361367 pub fn find_tag_unsigned < T : TryFrom < u64 > > ( & mut self , tag : Tag ) -> TiffResult < Option < T > > {
1337- self . image_ifd ( ) . find_tag_unsigned ( tag)
1368+ self . current_directory_ifd ( ) . find_tag_unsigned ( tag)
13381369 }
13391370
13401371 /// Tries to retrieve a tag from the current image directory and convert it to the desired
13411372 /// unsigned type. Returns an error if the tag is not present.
13421373 pub fn get_tag_unsigned < T : TryFrom < u64 > > ( & mut self , tag : Tag ) -> TiffResult < T > {
1343- self . image_ifd ( ) . get_tag_unsigned ( tag)
1374+ self . current_directory_ifd ( ) . get_tag_unsigned ( tag)
13441375 }
13451376
13461377 /// Tries to retrieve a tag from the current image directory.
13471378 /// Returns an error if the tag is not present
13481379 pub fn get_tag ( & mut self , tag : Tag ) -> TiffResult < ifd:: Value > {
1349- self . image_ifd ( ) . get_tag ( tag)
1380+ self . current_directory_ifd ( ) . get_tag ( tag)
13501381 }
13511382
13521383 pub fn get_tag_u32 ( & mut self , tag : Tag ) -> TiffResult < u32 > {
@@ -1401,7 +1432,7 @@ impl<R: Read + Seek> Decoder<R> {
14011432 }
14021433
14031434 pub fn tag_iter ( & mut self ) -> impl Iterator < Item = TiffResult < ( Tag , ifd:: Value ) > > + ' _ {
1404- self . image_ifd ( ) . tag_iter ( )
1435+ self . current_directory_ifd ( ) . tag_iter ( )
14051436 }
14061437}
14071438
0 commit comments