Skip to content

Commit

Permalink
Merge pull request #7975 from radarhere/libtiff
Browse files Browse the repository at this point in the history
Corrected check for libtiff feature
  • Loading branch information
radarhere committed Apr 21, 2024
2 parents f8160b8 + 11ac0c1 commit eee633c
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 95 deletions.
133 changes: 65 additions & 68 deletions Tests/test_file_libtiff.py
Expand Up @@ -185,7 +185,9 @@ def test_write_metadata(self, legacy_api: bool, tmp_path: Path) -> None:
assert field in reloaded, f"{field} not in metadata"

@pytest.mark.valgrind_known_error(reason="Known invalid metadata")
def test_additional_metadata(self, tmp_path: Path) -> None:
def test_additional_metadata(
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
# these should not crash. Seriously dummy data, most of it doesn't make
# any sense, so we're running up against limits where we're asking
# libtiff to do stupid things.
Expand Down Expand Up @@ -236,12 +238,10 @@ def test_additional_metadata(self, tmp_path: Path) -> None:
del new_ifd[338]

out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)

im.save(out, tiffinfo=new_ifd)

TiffImagePlugin.WRITE_LIBTIFF = False

def test_custom_metadata(self, tmp_path: Path) -> None:
class Tc(NamedTuple):
value: Any
Expand Down Expand Up @@ -343,24 +343,24 @@ def test_subifd(self, tmp_path: Path) -> None:
# Should not segfault
im.save(outfile)

def test_xmlpacket_tag(self, tmp_path: Path) -> None:
TiffImagePlugin.WRITE_LIBTIFF = True
def test_xmlpacket_tag(
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)

out = str(tmp_path / "temp.tif")
hopper().save(out, tiffinfo={700: b"xmlpacket tag"})
TiffImagePlugin.WRITE_LIBTIFF = False

with Image.open(out) as reloaded:
if 700 in reloaded.tag_v2:
assert reloaded.tag_v2[700] == b"xmlpacket tag"

def test_int_dpi(self, tmp_path: Path) -> None:
def test_int_dpi(self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
# issue #1765
im = hopper("RGB")
out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
im.save(out, dpi=(72, 72))
TiffImagePlugin.WRITE_LIBTIFF = False
with Image.open(out) as reloaded:
assert reloaded.info["dpi"] == (72.0, 72.0)

Expand Down Expand Up @@ -422,13 +422,13 @@ def test_g4_string_info(self, tmp_path: Path) -> None:
assert "temp.tif" == reread.tag_v2[269]
assert "temp.tif" == reread.tag[269][0]

def test_12bit_rawmode(self) -> None:
def test_12bit_rawmode(self, monkeypatch: pytest.MonkeyPatch) -> None:
"""Are we generating the same interpretation
of the image as Imagemagick is?"""
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/12bit.cropped.tif") as im:
im.load()
TiffImagePlugin.READ_LIBTIFF = False
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", False)
# to make the target --
# convert 12bit.cropped.tif -depth 16 tmp.tif
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
Expand Down Expand Up @@ -514,12 +514,13 @@ def test_cmyk_save(self, tmp_path: Path) -> None:
assert_image_equal_tofile(im, out)

@pytest.mark.parametrize("im", (hopper("P"), Image.new("P", (1, 1), "#000")))
def test_palette_save(self, im: Image.Image, tmp_path: Path) -> None:
def test_palette_save(
self, im: Image.Image, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
out = str(tmp_path / "temp.tif")

TiffImagePlugin.WRITE_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
im.save(out)
TiffImagePlugin.WRITE_LIBTIFF = False

with Image.open(out) as reloaded:
# colormap/palette tag
Expand Down Expand Up @@ -548,9 +549,9 @@ def test_fp_leak(self) -> None:
with pytest.raises(OSError):
os.close(fn)

def test_multipage(self) -> None:
def test_multipage(self, monkeypatch: pytest.MonkeyPatch) -> None:
# issue #862
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/multipage.tiff") as im:
# file is a multipage tiff, 10x10 green, 10x10 red, 20x20 blue

Expand All @@ -569,11 +570,9 @@ def test_multipage(self) -> None:
assert im.size == (20, 20)
assert im.convert("RGB").getpixel((0, 0)) == (0, 0, 255)

TiffImagePlugin.READ_LIBTIFF = False

def test_multipage_nframes(self) -> None:
def test_multipage_nframes(self, monkeypatch: pytest.MonkeyPatch) -> None:
# issue #862
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/multipage.tiff") as im:
frames = im.n_frames
assert frames == 3
Expand All @@ -582,35 +581,30 @@ def test_multipage_nframes(self) -> None:
# Should not raise ValueError: I/O operation on closed file
im.load()

TiffImagePlugin.READ_LIBTIFF = False

def test_multipage_seek_backwards(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
def test_multipage_seek_backwards(self, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/multipage.tiff") as im:
im.seek(1)
im.load()

im.seek(0)
assert im.convert("RGB").getpixel((0, 0)) == (0, 128, 0)

TiffImagePlugin.READ_LIBTIFF = False

def test__next(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
def test__next(self, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/hopper.tif") as im:
assert not im.tag.next
im.load()
assert not im.tag.next

def test_4bit(self) -> None:
def test_4bit(self, monkeypatch: pytest.MonkeyPatch) -> None:
# Arrange
test_file = "Tests/images/hopper_gray_4bpp.tif"
original = hopper("L")

# Act
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open(test_file) as im:
TiffImagePlugin.READ_LIBTIFF = False

# Assert
assert im.size == (128, 128)
Expand Down Expand Up @@ -650,12 +644,12 @@ def test_gray_semibyte_per_pixel(self) -> None:
assert im2.mode == "L"
assert_image_equal(im, im2)

def test_save_bytesio(self) -> None:
def test_save_bytesio(self, monkeypatch: pytest.MonkeyPatch) -> None:
# PR 1011
# Test TIFF saving to io.BytesIO() object.

TiffImagePlugin.WRITE_LIBTIFF = True
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)

# Generate test image
pilim = hopper()
Expand All @@ -672,9 +666,6 @@ def save_bytesio(compression: str | None = None) -> None:
save_bytesio("packbits")
save_bytesio("tiff_lzw")

TiffImagePlugin.WRITE_LIBTIFF = False
TiffImagePlugin.READ_LIBTIFF = False

def test_save_ycbcr(self, tmp_path: Path) -> None:
im = hopper("YCbCr")
outfile = str(tmp_path / "temp.tif")
Expand All @@ -694,15 +685,16 @@ def test_exif_ifd(self, tmp_path: Path) -> None:
if Image.core.libtiff_support_custom_tags:
assert reloaded.tag_v2[34665] == 125456

def test_crashing_metadata(self, tmp_path: Path) -> None:
def test_crashing_metadata(
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
# issue 1597
with Image.open("Tests/images/rdf.tif") as im:
out = str(tmp_path / "temp.tif")

TiffImagePlugin.WRITE_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
# this shouldn't crash
im.save(out, format="TIFF")
TiffImagePlugin.WRITE_LIBTIFF = False

def test_page_number_x_0(self, tmp_path: Path) -> None:
# Issue 973
Expand Down Expand Up @@ -733,36 +725,41 @@ def test_fd_duplication(self, tmp_path: Path) -> None:
# Should not raise PermissionError.
os.remove(tmpfile)

def test_read_icc(self) -> None:
def test_read_icc(self, monkeypatch: pytest.MonkeyPatch) -> None:
with Image.open("Tests/images/hopper.iccprofile.tif") as img:
icc = img.info.get("icc_profile")
assert icc is not None
TiffImagePlugin.READ_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/hopper.iccprofile.tif") as img:
icc_libtiff = img.info.get("icc_profile")
assert icc_libtiff is not None
TiffImagePlugin.READ_LIBTIFF = False
assert icc == icc_libtiff

def test_write_icc(self, tmp_path: Path) -> None:
def check_write(libtiff: bool) -> None:
TiffImagePlugin.WRITE_LIBTIFF = libtiff

with Image.open("Tests/images/hopper.iccprofile.tif") as img:
icc_profile = img.info["icc_profile"]

out = str(tmp_path / "temp.tif")
img.save(out, icc_profile=icc_profile)
with Image.open(out) as reloaded:
assert icc_profile == reloaded.info["icc_profile"]
@pytest.mark.parametrize(
"libtiff",
(
pytest.param(
True,
marks=pytest.mark.skipif(
not Image.core.libtiff_support_custom_tags,
reason="Custom tags not supported by older libtiff",
),
),
False,
),
)
def test_write_icc(
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path, libtiff: bool
) -> None:
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", libtiff)

libtiffs = []
if Image.core.libtiff_support_custom_tags:
libtiffs.append(True)
libtiffs.append(False)
with Image.open("Tests/images/hopper.iccprofile.tif") as img:
icc_profile = img.info["icc_profile"]

for libtiff in libtiffs:
check_write(libtiff)
out = str(tmp_path / "temp.tif")
img.save(out, icc_profile=icc_profile)
with Image.open(out) as reloaded:
assert icc_profile == reloaded.info["icc_profile"]

def test_multipage_compression(self) -> None:
with Image.open("Tests/images/compression.tif") as im:
Expand Down Expand Up @@ -840,12 +837,13 @@ def test_sampleformat(self) -> None:

assert_image_equal_tofile(im, "Tests/images/copyleft.png", mode="RGB")

def test_sampleformat_write(self, tmp_path: Path) -> None:
def test_sampleformat_write(
self, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
im = Image.new("F", (1, 1))
out = str(tmp_path / "temp.tif")
TiffImagePlugin.WRITE_LIBTIFF = True
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", True)
im.save(out)
TiffImagePlugin.WRITE_LIBTIFF = False

with Image.open(out) as reloaded:
assert reloaded.mode == "F"
Expand Down Expand Up @@ -1091,15 +1089,14 @@ def test_sampleformat_not_corrupted(self) -> None:
with Image.open(out) as im:
im.load()

def test_realloc_overflow(self) -> None:
TiffImagePlugin.READ_LIBTIFF = True
def test_realloc_overflow(self, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", True)
with Image.open("Tests/images/tiff_overflow_rows_per_strip.tif") as im:
with pytest.raises(OSError) as e:
im.load()

# Assert that the error code is IMAGING_CODEC_MEMORY
assert str(e.value) == "-9"
TiffImagePlugin.READ_LIBTIFF = False

@pytest.mark.parametrize("compression", ("tiff_adobe_deflate", "jpeg"))
def test_save_multistrip(self, compression: str, tmp_path: Path) -> None:
Expand Down
17 changes: 5 additions & 12 deletions Tests/test_imagesequence.py
Expand Up @@ -47,25 +47,18 @@ def test_iterator_min_frame() -> None:
assert i[index] == next(i)


def _test_multipage_tiff() -> None:
@pytest.mark.parametrize(
"libtiff", (pytest.param(True, marks=skip_unless_feature("libtiff")), False)
)
def test_multipage_tiff(monkeypatch: pytest.MonkeyPatch, libtiff: bool) -> None:
monkeypatch.setattr(TiffImagePlugin, "READ_LIBTIFF", libtiff)
with Image.open("Tests/images/multipage.tiff") as im:
for index, frame in enumerate(ImageSequence.Iterator(im)):
frame.load()
assert index == im.tell()
frame.convert("RGB")


def test_tiff() -> None:
_test_multipage_tiff()


@skip_unless_feature("libtiff")
def test_libtiff() -> None:
TiffImagePlugin.READ_LIBTIFF = True
_test_multipage_tiff()
TiffImagePlugin.READ_LIBTIFF = False


def test_consecutive() -> None:
with Image.open("Tests/images/multipage.tiff") as im:
first_frame = None
Expand Down
32 changes: 17 additions & 15 deletions Tests/test_tiff_ifdrational.py
Expand Up @@ -3,10 +3,12 @@
from fractions import Fraction
from pathlib import Path

from PIL import Image, TiffImagePlugin, features
import pytest

from PIL import Image, TiffImagePlugin
from PIL.TiffImagePlugin import IFDRational

from .helper import hopper
from .helper import hopper, skip_unless_feature


def _test_equal(num, denom, target) -> None:
Expand Down Expand Up @@ -52,18 +54,18 @@ def test_nonetype() -> None:
assert xres and yres


def test_ifd_rational_save(tmp_path: Path) -> None:
methods = [True]
if features.check("libtiff"):
methods.append(False)

for libtiff in methods:
TiffImagePlugin.WRITE_LIBTIFF = libtiff
@pytest.mark.parametrize(
"libtiff", (pytest.param(True, marks=skip_unless_feature("libtiff")), False)
)
def test_ifd_rational_save(
monkeypatch: pytest.MonkeyPatch, tmp_path: Path, libtiff: bool
) -> None:
im = hopper()
out = str(tmp_path / "temp.tiff")
res = IFDRational(301, 1)

im = hopper()
out = str(tmp_path / "temp.tiff")
res = IFDRational(301, 1)
im.save(out, dpi=(res, res), compression="raw")
monkeypatch.setattr(TiffImagePlugin, "WRITE_LIBTIFF", libtiff)
im.save(out, dpi=(res, res), compression="raw")

with Image.open(out) as reloaded:
assert float(IFDRational(301, 1)) == float(reloaded.tag_v2[282])
with Image.open(out) as reloaded:
assert float(IFDRational(301, 1)) == float(reloaded.tag_v2[282])

0 comments on commit eee633c

Please sign in to comment.