@@ -1216,10 +1216,6 @@ def seek(self, frame: int) -> None:
12161216 def _seek (self , frame : int ) -> None :
12171217 self .fp = self ._fp
12181218
1219- # reset buffered io handle in case fp
1220- # was passed to libtiff, invalidating the buffer
1221- self .fp .tell ()
1222-
12231219 while len (self ._frame_pos ) <= frame :
12241220 if not self .__next :
12251221 msg = "no more images in TIFF file"
@@ -1303,10 +1299,6 @@ def load_end(self) -> None:
13031299 if not self .is_animated :
13041300 self ._close_exclusive_fp_after_loading = True
13051301
1306- # reset buffered io handle in case fp
1307- # was passed to libtiff, invalidating the buffer
1308- self .fp .tell ()
1309-
13101302 # load IFD data from fp before it is closed
13111303 exif = self .getexif ()
13121304 for key in TiffTags .TAGS_V2_GROUPS :
@@ -1381,8 +1373,17 @@ def _load_libtiff(self) -> Image.core.PixelAccess | None:
13811373 logger .debug ("have fileno, calling fileno version of the decoder." )
13821374 if not close_self_fp :
13831375 self .fp .seek (0 )
1376+ # Save and restore the file position, because libtiff will move it
1377+ # outside of the Python runtime, and that will confuse
1378+ # io.BufferedReader and possible others.
1379+ # NOTE: This must use os.lseek(), and not fp.tell()/fp.seek(),
1380+ # because the buffer read head already may not equal the actual
1381+ # file position, and fp.seek() may just adjust it's internal
1382+ # pointer and not actually seek the OS file handle.
1383+ pos = os .lseek (fp , 0 , os .SEEK_CUR )
13841384 # 4 bytes, otherwise the trace might error out
13851385 n , err = decoder .decode (b"fpfp" )
1386+ os .lseek (fp , pos , os .SEEK_SET )
13861387 else :
13871388 # we have something else.
13881389 logger .debug ("don't have fileno or getvalue. just reading" )
0 commit comments