Skip to content

TIFF: report correct image size after opening #8387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Tests/test_image_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,6 @@ def test_copy_zero() -> None:
@skip_unless_feature("libtiff")
def test_deepcopy() -> None:
with Image.open("Tests/images/g4_orientation_5.tif") as im:
assert im.size == (590, 88)
out = copy.deepcopy(im)
assert out.size == (590, 88)
9 changes: 0 additions & 9 deletions Tests/test_image_resize.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
assert_image_equal_tofile,
assert_image_similar,
hopper,
skip_unless_feature,
)


Expand Down Expand Up @@ -299,14 +298,6 @@ def resize(mode: str, size: tuple[int, int] | list[int]) -> None:
with pytest.raises(ValueError):
im.resize((10, 10), "unknown")

@skip_unless_feature("libtiff")
def test_load_first(self) -> None:
# load() may change the size of the image
# Test that resize() is calling it before getting the size
with Image.open("Tests/images/g4_orientation_5.tif") as im:
im = im.resize((64, 64))
assert im.size == (64, 64)

@pytest.mark.parametrize("mode", ("L", "RGB", "I", "F"))
def test_default_filter_bicubic(self, mode: str) -> None:
im = hopper(mode)
Expand Down
16 changes: 0 additions & 16 deletions Tests/test_image_thumbnail.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
assert_image_similar,
fromstring,
hopper,
skip_unless_feature,
tostring,
)

Expand Down Expand Up @@ -91,21 +90,6 @@ def test_no_resize() -> None:
assert im.size == (64, 64)


@skip_unless_feature("libtiff")
def test_load_first() -> None:
# load() may change the size of the image
# Test that thumbnail() is calling it before performing size calculations
with Image.open("Tests/images/g4_orientation_5.tif") as im:
im.thumbnail((64, 64))
assert im.size == (64, 10)

# Test thumbnail(), without draft(),
# on an image that is large enough once load() has changed the size
with Image.open("Tests/images/g4_orientation_5.tif") as im:
im.thumbnail((590, 88), reducing_gap=None)
assert im.size == (590, 88)


def test_load_first_unless_jpeg() -> None:
# Test that thumbnail() still uses draft() for JPEG
with Image.open("Tests/images/hopper.jpg") as im:
Expand Down
3 changes: 2 additions & 1 deletion Tests/test_numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,9 @@ def test_zero_size() -> None:
@skip_unless_feature("libtiff")
def test_load_first() -> None:
with Image.open("Tests/images/g4_orientation_5.tif") as im:
assert im.size == (590, 88)
a = numpy.array(im)
assert a.shape == (88, 590)
assert a.shape == (88, 590)


def test_bool() -> None:
Expand Down
5 changes: 3 additions & 2 deletions src/PIL/ImageFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,8 +322,9 @@ def load(self) -> Image.core.PixelAccess | None:

def load_prepare(self) -> None:
# create image memory if necessary
if self._im is None or self.im.mode != self.mode or self.im.size != self.size:
self.im = Image.core.new(self.mode, self.size)
# use internal _size property for correct tile size
if self._im is None or self.im.mode != self.mode or self.im.size != self._size:
self.im = Image.core.new(self.mode, self._size)
# create palette (optional)
if self.mode == "P":
Image.Image.load(self)
Expand Down
13 changes: 10 additions & 3 deletions src/PIL/TiffImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,13 @@ def load(self) -> Image.core.PixelAccess | None:
return self._load_libtiff()
return super().load()

@property
def size(self) -> tuple[int, int]:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is differ from uploadcare@1d77bfe since for me it looks less magical, but if you can't agree, I can copy the previous as is

if hasattr(self, "tag_v2"):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a cases after copying or pickling, when the class is actually TiffImageFile, but it is loaded and doesn't have tag_v2 attribute

if self.tag_v2.get(ExifTags.Base.Orientation) in (5, 6, 7, 8):
return (self._size[1], self._size[0])
return self._size

def load_end(self) -> None:
# allow closing if we're on the first frame, there's no next
# This is the ImageFile.load path only, libtiff specific below.
Expand Down Expand Up @@ -1559,7 +1566,7 @@ def _setup(self) -> None:
if STRIPOFFSETS in self.tag_v2:
offsets = self.tag_v2[STRIPOFFSETS]
h = self.tag_v2.get(ROWSPERSTRIP, ysize)
w = self.size[0]
w = xsize
else:
# tiled image
offsets = self.tag_v2[TILEOFFSETS]
Expand Down Expand Up @@ -1593,9 +1600,9 @@ def _setup(self) -> None:
)
)
x = x + w
if x >= self.size[0]:
if x >= xsize:
x, y = 0, y + h
if y >= self.size[1]:
if y >= ysize:
x = y = 0
layer += 1
else:
Expand Down
Loading