1- use std:: collections:: { HashMap , HashSet } ;
1+ use std:: collections:: { BTreeMap , HashSet } ;
22use std:: io:: { self , Read , Seek } ;
33
44use crate :: tags:: {
5- CompressionMethod , PhotometricInterpretation , PlanarConfiguration , Predictor , SampleFormat ,
6- Tag , Type ,
5+ CompressionMethod , IfdPointer , PhotometricInterpretation , PlanarConfiguration , Predictor ,
6+ SampleFormat , Tag , Type ,
77} ;
88use crate :: {
9- bytecast, ColorType , TiffError , TiffFormatError , TiffResult , TiffUnsupportedError , UsageError ,
9+ bytecast, ColorType , Directory , TiffError , TiffFormatError , TiffResult , TiffUnsupportedError ,
10+ UsageError ,
1011} ;
1112use half:: f16;
1213
13- use self :: ifd:: Directory ;
1414use self :: image:: Image ;
1515use self :: stream:: { ByteOrder , EndianReader } ;
1616
@@ -263,9 +263,9 @@ where
263263 reader : EndianReader < R > ,
264264 bigtiff : bool ,
265265 limits : Limits ,
266- next_ifd : Option < u64 > ,
267- ifd_offsets : Vec < u64 > ,
268- seen_ifds : HashSet < u64 > ,
266+ next_ifd : Option < IfdPointer > ,
267+ ifd_offsets : Vec < IfdPointer > ,
268+ seen_ifds : HashSet < IfdPointer > ,
269269 image : Image ,
270270}
271271
@@ -487,11 +487,13 @@ impl<R: Read + Seek> Decoder<R> {
487487 ) )
488488 }
489489 } ;
490+
490491 let next_ifd = if bigtiff {
491492 Some ( reader. read_u64 ( ) ?)
492493 } else {
493494 Some ( u64:: from ( reader. read_u32 ( ) ?) )
494- } ;
495+ }
496+ . map ( IfdPointer ) ;
495497
496498 let mut seen_ifds = HashSet :: new ( ) ;
497499 seen_ifds. insert ( * next_ifd. as_ref ( ) . unwrap ( ) ) ;
@@ -557,9 +559,9 @@ impl<R: Read + Seek> Decoder<R> {
557559
558560 loop {
559561 // Follow the list until we find the one we want, or we reach the end, whichever happens first
560- let ( _ifd , next_ifd ) = self . next_ifd ( ) ?;
562+ let ifd = self . next_ifd ( ) ?;
561563
562- if next_ifd . is_none ( ) {
564+ if ifd . next ( ) . is_none ( ) {
563565 break ;
564566 }
565567
@@ -571,8 +573,7 @@ impl<R: Read + Seek> Decoder<R> {
571573
572574 // If the index is within the list of ifds then we can load the selected image/IFD
573575 if let Some ( ifd_offset) = self . ifd_offsets . get ( ifd_index) {
574- let ( ifd, _next_ifd) = Self :: read_ifd ( & mut self . reader , self . bigtiff , * ifd_offset) ?;
575-
576+ let ifd = Self :: read_ifd ( & mut self . reader , self . bigtiff , * ifd_offset) ?;
576577 self . image = Image :: from_reader ( & mut self . reader , ifd, & self . limits , self . bigtiff ) ?;
577578
578579 Ok ( ( ) )
@@ -583,36 +584,35 @@ impl<R: Read + Seek> Decoder<R> {
583584 }
584585 }
585586
586- fn next_ifd ( & mut self ) -> TiffResult < ( Directory , Option < u64 > ) > {
587+ fn next_ifd ( & mut self ) -> TiffResult < Directory > {
587588 if self . next_ifd . is_none ( ) {
588589 return Err ( TiffError :: FormatError (
589590 TiffFormatError :: ImageFileDirectoryNotFound ,
590591 ) ) ;
591592 }
592593
593- let ( ifd, next_ifd ) = Self :: read_ifd (
594+ let ifd = Self :: read_ifd (
594595 & mut self . reader ,
595596 self . bigtiff ,
596597 self . next_ifd . take ( ) . unwrap ( ) ,
597598 ) ?;
598599
599- if let Some ( next) = next_ifd {
600+ if let Some ( next) = ifd . next ( ) {
600601 if !self . seen_ifds . insert ( next) {
601602 return Err ( TiffError :: FormatError ( TiffFormatError :: CycleInOffsets ) ) ;
602603 }
603604 self . next_ifd = Some ( next) ;
604605 self . ifd_offsets . push ( next) ;
605606 }
606607
607- Ok ( ( ifd, next_ifd ) )
608+ Ok ( ifd)
608609 }
609610
610611 /// Reads in the next image.
611612 /// If there is no further image in the TIFF file a format error is returned.
612613 /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
613614 pub fn next_image ( & mut self ) -> TiffResult < ( ) > {
614- let ( ifd, _next_ifd) = self . next_ifd ( ) ?;
615-
615+ let ifd = self . next_ifd ( ) ?;
616616 self . image = Image :: from_reader ( & mut self . reader , ifd, & self . limits , self . bigtiff ) ?;
617617 Ok ( ( ) )
618618 }
@@ -734,6 +734,13 @@ impl<R: Read + Seek> Decoder<R> {
734734 self . reader . goto_offset ( offset)
735735 }
736736
737+ /// Read a directory from a known offset.
738+ ///
739+ /// This may always modify the position of the reader.
740+ pub fn read_directory ( & mut self , ptr : IfdPointer ) -> TiffResult < Directory > {
741+ Self :: read_ifd ( & mut self . reader , self . bigtiff , ptr)
742+ }
743+
737744 /// Reads a IFD entry.
738745 // An IFD entry has four fields:
739746 //
@@ -775,25 +782,27 @@ impl<R: Read + Seek> Decoder<R> {
775782 fn read_ifd (
776783 reader : & mut EndianReader < R > ,
777784 bigtiff : bool ,
778- ifd_location : u64 ,
779- ) -> TiffResult < ( Directory , Option < u64 > ) > {
780- reader. goto_offset ( ifd_location) ?;
785+ ifd_location : IfdPointer ,
786+ ) -> TiffResult < Directory > {
787+ reader. goto_offset ( ifd_location. 0 ) ?;
781788
782- let mut dir : Directory = HashMap :: new ( ) ;
789+ let mut entries : BTreeMap < _ , _ > = BTreeMap :: new ( ) ;
783790
784791 let num_tags = if bigtiff {
785792 reader. read_u64 ( ) ?
786793 } else {
787794 reader. read_u16 ( ) ?. into ( )
788795 } ;
796+
789797 for _ in 0 ..num_tags {
790798 let ( tag, entry) = match Self :: read_entry ( reader, bigtiff) ? {
791799 Some ( val) => val,
792800 None => {
793801 continue ;
794802 } // Unknown data type in tag, skip
795803 } ;
796- dir. insert ( tag, entry) ;
804+
805+ entries. insert ( tag. to_u16 ( ) , entry) ;
797806 }
798807
799808 let next_ifd = if bigtiff {
@@ -802,18 +811,15 @@ impl<R: Read + Seek> Decoder<R> {
802811 reader. read_u32 ( ) ?. into ( )
803812 } ;
804813
805- let next_ifd = match next_ifd {
806- 0 => None ,
807- _ => Some ( next_ifd) ,
808- } ;
814+ let next_ifd = core:: num:: NonZeroU64 :: new ( next_ifd) ;
809815
810- Ok ( ( dir , next_ifd) )
816+ Ok ( Directory { entries , next_ifd } )
811817 }
812818
813819 /// Tries to retrieve a tag.
814820 /// Return `Ok(None)` if the tag is not present.
815821 pub fn find_tag ( & mut self , tag : Tag ) -> TiffResult < Option < ifd:: Value > > {
816- let entry = match self . image ( ) . ifd . as_ref ( ) . unwrap ( ) . get ( & tag) {
822+ let entry = match self . image ( ) . ifd . as_ref ( ) . unwrap ( ) . get ( tag) {
817823 None => return Ok ( None ) ,
818824 Some ( entry) => entry. clone ( ) ,
819825 } ;
@@ -928,7 +934,7 @@ impl<R: Read + Seek> Decoder<R> {
928934 self . image . ifd . as_ref ( ) . unwrap ( ) . iter ( ) . map ( |( tag, entry) | {
929935 entry
930936 . val ( & self . limits , self . bigtiff , & mut self . reader )
931- . map ( |value| ( * tag, value) )
937+ . map ( |value| ( tag, value) )
932938 } )
933939 }
934940
0 commit comments