mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-09-19 02:32:27 +03:00
160 lines
4.0 KiB
Python
160 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
from io import BytesIO
|
|
|
|
import pytest
|
|
|
|
from PIL import Image, IptcImagePlugin, TiffImagePlugin, TiffTags
|
|
|
|
from .helper import assert_image_equal, hopper
|
|
|
|
TEST_FILE = "Tests/images/iptc.jpg"
|
|
|
|
|
|
def create_iptc_image(info: dict[str, int] = {}) -> BytesIO:
|
|
def field(tag, value):
|
|
return bytes((0x1C,) + tag + (0, len(value))) + value
|
|
|
|
data = field((3, 60), bytes((info.get("layers", 1), info.get("component", 0))))
|
|
data += field((3, 120), bytes((info.get("compression", 1),)))
|
|
if "band" in info:
|
|
data += field((3, 65), bytes((info["band"] + 1,)))
|
|
data += field((3, 20), b"\x01") # width
|
|
data += field((3, 30), b"\x01") # height
|
|
data += field(
|
|
(8, 10),
|
|
bytes((info.get("data", 0),)),
|
|
)
|
|
|
|
return BytesIO(data)
|
|
|
|
|
|
def test_open() -> None:
|
|
expected = Image.new("L", (1, 1))
|
|
|
|
f = create_iptc_image()
|
|
with Image.open(f) as im:
|
|
assert im.tile == [("iptc", (0, 0, 1, 1), 25, ("raw", None))]
|
|
assert_image_equal(im, expected)
|
|
|
|
with Image.open(f) as im:
|
|
assert im.load() is not None
|
|
|
|
|
|
def test_field_length() -> None:
|
|
f = create_iptc_image()
|
|
f.seek(28)
|
|
f.write(b"\xff")
|
|
with pytest.raises(OSError, match="illegal field length in IPTC/NAA file"):
|
|
with Image.open(f):
|
|
pass
|
|
|
|
|
|
@pytest.mark.parametrize("layers, mode", ((3, "RGB"), (4, "CMYK")))
|
|
def test_layers(layers: int, mode: str) -> None:
|
|
for band in range(-1, layers):
|
|
info = {"layers": layers, "component": 1, "data": 5}
|
|
if band != -1:
|
|
info["band"] = band
|
|
f = create_iptc_image(info)
|
|
with Image.open(f) as im:
|
|
assert im.mode == mode
|
|
|
|
data = [0] * layers
|
|
data[max(band, 0)] = 5
|
|
assert im.getpixel((0, 0)) == tuple(data)
|
|
|
|
|
|
def test_unknown_compression() -> None:
|
|
f = create_iptc_image({"compression": 2})
|
|
with pytest.raises(OSError, match="Unknown IPTC image compression"):
|
|
with Image.open(f):
|
|
pass
|
|
|
|
|
|
def test_getiptcinfo() -> None:
|
|
f = create_iptc_image()
|
|
with Image.open(f) as im:
|
|
assert IptcImagePlugin.getiptcinfo(im) == {
|
|
(3, 60): b"\x01\x00",
|
|
(3, 120): b"\x01",
|
|
(3, 20): b"\x01",
|
|
(3, 30): b"\x01",
|
|
}
|
|
|
|
|
|
def test_getiptcinfo_jpg_none() -> None:
|
|
# Arrange
|
|
with hopper() as im:
|
|
# Act
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
# Assert
|
|
assert iptc is None
|
|
|
|
|
|
def test_getiptcinfo_jpg_found() -> None:
|
|
# Arrange
|
|
with Image.open(TEST_FILE) as im:
|
|
# Act
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
# Assert
|
|
assert isinstance(iptc, dict)
|
|
assert iptc[(2, 90)] == b"Budapest"
|
|
assert iptc[(2, 101)] == b"Hungary"
|
|
|
|
|
|
def test_getiptcinfo_fotostation() -> None:
|
|
# Arrange
|
|
with open(TEST_FILE, "rb") as fp:
|
|
data = bytearray(fp.read())
|
|
data[86] = 240
|
|
f = BytesIO(data)
|
|
with Image.open(f) as im:
|
|
# Act
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
# Assert
|
|
assert iptc is not None
|
|
assert 240 in (tag[0] for tag in iptc.keys()), "FotoStation tag not found"
|
|
|
|
|
|
def test_getiptcinfo_zero_padding() -> None:
|
|
# Arrange
|
|
with Image.open(TEST_FILE) as im:
|
|
im.info["photoshop"][0x0404] += b"\x00\x00\x00"
|
|
|
|
# Act
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
# Assert
|
|
assert isinstance(iptc, dict)
|
|
assert len(iptc) == 3
|
|
|
|
|
|
def test_getiptcinfo_tiff() -> None:
|
|
expected = {(1, 90): b"\x1b%G", (2, 0): b"\xcf\xc0"}
|
|
|
|
with Image.open("Tests/images/hopper.Lab.tif") as im:
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
assert iptc == expected
|
|
|
|
# Test with LONG tag type
|
|
with Image.open("Tests/images/hopper.Lab.tif") as im:
|
|
im.tag_v2.tagtype[TiffImagePlugin.IPTC_NAA_CHUNK] = TiffTags.LONG
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
assert iptc == expected
|
|
|
|
|
|
def test_getiptcinfo_tiff_none() -> None:
|
|
# Arrange
|
|
with Image.open("Tests/images/hopper.tif") as im:
|
|
# Act
|
|
iptc = IptcImagePlugin.getiptcinfo(im)
|
|
|
|
# Assert
|
|
assert iptc is None
|