mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-26 16:50:33 +03:00
Fix file position desync when calling into libtiff
This commit is contained in:
parent
0995305eb4
commit
c7a9582eab
23
Tests/test_libtiff_file_position.py
Normal file
23
Tests/test_libtiff_file_position.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('test_file', [
|
||||||
|
'Tests/images/old-style-jpeg-compression-no-samplesperpixel.tif',
|
||||||
|
'Tests/images/old-style-jpeg-compression.tif',
|
||||||
|
])
|
||||||
|
def test_libtiff_exif_loading(test_file) -> None:
|
||||||
|
# loading image before exif
|
||||||
|
im1 = Image.open(open(test_file, 'rb', buffering=1048576))
|
||||||
|
im1.load()
|
||||||
|
exif1 = dict(im1.getexif())
|
||||||
|
|
||||||
|
# loading exif before image
|
||||||
|
im2 = Image.open(open(test_file, 'rb', buffering=1048576))
|
||||||
|
exif2 = dict(im2.getexif())
|
||||||
|
|
||||||
|
assert exif1 == exif2
|
|
@ -1216,10 +1216,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
def _seek(self, frame: int) -> None:
|
def _seek(self, frame: int) -> None:
|
||||||
self.fp = self._fp
|
self.fp = self._fp
|
||||||
|
|
||||||
# reset buffered io handle in case fp
|
|
||||||
# was passed to libtiff, invalidating the buffer
|
|
||||||
self.fp.tell()
|
|
||||||
|
|
||||||
while len(self._frame_pos) <= frame:
|
while len(self._frame_pos) <= frame:
|
||||||
if not self.__next:
|
if not self.__next:
|
||||||
msg = "no more images in TIFF file"
|
msg = "no more images in TIFF file"
|
||||||
|
@ -1303,10 +1299,6 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
if not self.is_animated:
|
if not self.is_animated:
|
||||||
self._close_exclusive_fp_after_loading = True
|
self._close_exclusive_fp_after_loading = True
|
||||||
|
|
||||||
# reset buffered io handle in case fp
|
|
||||||
# was passed to libtiff, invalidating the buffer
|
|
||||||
self.fp.tell()
|
|
||||||
|
|
||||||
# load IFD data from fp before it is closed
|
# load IFD data from fp before it is closed
|
||||||
exif = self.getexif()
|
exif = self.getexif()
|
||||||
for key in TiffTags.TAGS_V2_GROUPS:
|
for key in TiffTags.TAGS_V2_GROUPS:
|
||||||
|
@ -1381,8 +1373,17 @@ class TiffImageFile(ImageFile.ImageFile):
|
||||||
logger.debug("have fileno, calling fileno version of the decoder.")
|
logger.debug("have fileno, calling fileno version of the decoder.")
|
||||||
if not close_self_fp:
|
if not close_self_fp:
|
||||||
self.fp.seek(0)
|
self.fp.seek(0)
|
||||||
|
# Save and restore the file position, because libtiff will move it
|
||||||
|
# outside of the python runtime, and that will confuse
|
||||||
|
# io.BufferedReader and possible others.
|
||||||
|
# NOTE: This must use os.lseek(), and not fp.tell()/fp.seek(),
|
||||||
|
# because the buffer read head already may not equal the actual
|
||||||
|
# file position, and fp.seek() may just adjust it's internal
|
||||||
|
# pointer and not actually seek the OS file handle.
|
||||||
|
pos = os.lseek(fp, 0, os.SEEK_CUR)
|
||||||
# 4 bytes, otherwise the trace might error out
|
# 4 bytes, otherwise the trace might error out
|
||||||
n, err = decoder.decode(b"fpfp")
|
n, err = decoder.decode(b"fpfp")
|
||||||
|
os.lseek(fp, pos, os.SEEK_SET)
|
||||||
else:
|
else:
|
||||||
# we have something else.
|
# we have something else.
|
||||||
logger.debug("don't have fileno or getvalue. just reading")
|
logger.debug("don't have fileno or getvalue. just reading")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user