Pillow/Tests/test_file_jxl_metadata.py
2025-05-09 20:41:20 +10:00

121 lines
3.4 KiB
Python

from __future__ import annotations
from types import ModuleType
import pytest
from PIL import Image, JpegXlImagePlugin
from .helper import skip_unless_feature
pytestmark = [skip_unless_feature("jpegxl")]
ElementTree: ModuleType | None
try:
from defusedxml import ElementTree
except ImportError:
ElementTree = None
# cjxl flower.jpg flower.jxl --lossless_jpeg=0 -q 75 -e 8
# >>> from PIL import Image
# >>> with Image.open('Tests/images/flower2.webp') as im:
# >>> with open('/tmp/xmp.xml', 'wb') as f:
# >>> f.write(im.info['xmp'])
# cjxl flower2.jpg flower2.jxl --lossless_jpeg=0 -q 75 -e 8 -x xmp=/tmp/xmp.xml
def test_read_exif_metadata() -> None:
with Image.open("Tests/images/flower.jxl") as im:
assert im.format == "JPEG XL"
exif_data = im.info["exif"]
exif = im.getexif()
# Camera make
assert exif[271] == "Canon"
with Image.open("Tests/images/flower.jpg") as im_jpeg:
expected_exif = im_jpeg.info["exif"]
# jpeg xl always returns exif without 'Exif\0\0' prefix
assert exif_data == expected_exif[6:]
def test_read_exif_metadata_without_prefix() -> None:
with Image.open("Tests/images/flower2.jxl") as im:
# Assert prefix is not present
assert im.info["exif"][:6] != b"Exif\x00\x00"
exif = im.getexif()
assert exif[305] == "Adobe Photoshop CS6 (Macintosh)"
def test_read_icc_profile() -> None:
with Image.open("Tests/images/flower2.jxl") as im:
assert im.format == "JPEG XL"
icc = im.info["icc_profile"]
with Image.open("Tests/images/flower2.jxl") as im_jpeg:
expected_icc = im_jpeg.info["icc_profile"]
assert icc == expected_icc
def test_getxmp() -> None:
with Image.open("Tests/images/flower.jxl") as im:
assert "xmp" not in im.info
if ElementTree is None:
with pytest.warns(
UserWarning,
match="XMP data cannot be read without defusedxml dependency",
):
xmp = im.getxmp()
else:
xmp = im.getxmp()
assert xmp == {}
with Image.open("Tests/images/flower2.jxl") as im:
if ElementTree is None:
with pytest.warns(
UserWarning,
match="XMP data cannot be read without defusedxml dependency",
):
assert im.getxmp() == {}
else:
assert "xmp" in im.info
assert (
im.getxmp()["xmpmeta"]["xmptk"]
== "Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 "
)
def test_4_byte_exif(monkeypatch: pytest.MonkeyPatch) -> None:
class _mock_jpegxl:
class JpegXlDecoder:
def __init__(self, b: bytes) -> None:
pass
def get_info(self) -> tuple[tuple[int, int], str, int, int, int, int, int]:
return ((1, 1), "L", 0, 0, 0, 0, 0)
def get_icc(self) -> None:
pass
def get_exif(self) -> bytes:
return b"\0\0\0\0"
def get_xmp(self) -> None:
pass
monkeypatch.setattr(JpegXlImagePlugin, "_jpegxl", _mock_jpegxl)
with Image.open("Tests/images/hopper.jxl") as im:
assert "exif" not in im.info
def test_read_exif_metadata_empty() -> None:
with Image.open("Tests/images/hopper.jxl") as im:
assert im.getexif() == {}