2023-12-21 14:13:31 +03:00
|
|
|
from __future__ import annotations
|
2024-01-20 14:23:03 +03:00
|
|
|
|
2019-10-07 16:28:36 +03:00
|
|
|
from io import BytesIO
|
2024-01-31 12:12:58 +03:00
|
|
|
from pathlib import Path
|
2024-02-12 13:06:17 +03:00
|
|
|
from types import ModuleType
|
2021-01-07 16:57:49 +03:00
|
|
|
|
2021-01-07 16:50:25 +03:00
|
|
|
import pytest
|
2021-01-07 16:57:49 +03:00
|
|
|
|
2024-09-09 15:34:46 +03:00
|
|
|
from PIL import Image, WebPImagePlugin
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2021-04-10 17:58:01 +03:00
|
|
|
from .helper import mark_if_feature_version, skip_unless_feature
|
2017-10-02 01:23:18 +03:00
|
|
|
|
2024-07-07 21:47:06 +03:00
|
|
|
pytestmark = skip_unless_feature("webp")
|
2020-02-18 16:50:34 +03:00
|
|
|
|
2024-02-12 13:06:17 +03:00
|
|
|
ElementTree: ModuleType | None
|
2022-11-25 00:47:40 +03:00
|
|
|
try:
|
|
|
|
from defusedxml import ElementTree
|
|
|
|
except ImportError:
|
|
|
|
ElementTree = None
|
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_read_exif_metadata() -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
file_path = "Tests/images/flower.webp"
|
|
|
|
with Image.open(file_path) as image:
|
2024-09-09 15:34:46 +03:00
|
|
|
assert isinstance(image, WebPImagePlugin.WebPImageFile)
|
2020-02-18 16:50:34 +03:00
|
|
|
assert image.format == "WEBP"
|
|
|
|
exif_data = image.info.get("exif", None)
|
|
|
|
assert exif_data
|
|
|
|
|
|
|
|
exif = image._getexif()
|
2024-09-09 15:34:46 +03:00
|
|
|
assert exif is not None
|
2020-02-18 16:50:34 +03:00
|
|
|
|
|
|
|
# Camera make
|
|
|
|
assert exif[271] == "Canon"
|
|
|
|
|
|
|
|
with Image.open("Tests/images/flower.jpg") as jpeg_image:
|
|
|
|
expected_exif = jpeg_image.info["exif"]
|
|
|
|
|
|
|
|
assert exif_data == expected_exif
|
|
|
|
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_read_exif_metadata_without_prefix() -> None:
|
2020-06-07 13:01:04 +03:00
|
|
|
with Image.open("Tests/images/flower2.webp") 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)"
|
|
|
|
|
2021-01-07 16:57:49 +03:00
|
|
|
|
2021-04-10 17:58:01 +03:00
|
|
|
@mark_if_feature_version(
|
|
|
|
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
|
|
|
)
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_write_exif_metadata() -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
file_path = "Tests/images/flower.jpg"
|
|
|
|
test_buffer = BytesIO()
|
|
|
|
with Image.open(file_path) as image:
|
|
|
|
expected_exif = image.info["exif"]
|
|
|
|
|
|
|
|
image.save(test_buffer, "webp", exif=expected_exif)
|
|
|
|
|
|
|
|
test_buffer.seek(0)
|
|
|
|
with Image.open(test_buffer) as webp_image:
|
|
|
|
webp_exif = webp_image.info.get("exif", None)
|
2022-09-15 14:25:40 +03:00
|
|
|
assert webp_exif == expected_exif[6:], "WebP EXIF didn't match"
|
2014-10-11 20:42:10 +04:00
|
|
|
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_read_icc_profile() -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
file_path = "Tests/images/flower2.webp"
|
|
|
|
with Image.open(file_path) as image:
|
|
|
|
assert image.format == "WEBP"
|
|
|
|
assert image.info.get("icc_profile", None)
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
icc = image.info["icc_profile"]
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
with Image.open("Tests/images/flower2.jpg") as jpeg_image:
|
|
|
|
expected_icc = jpeg_image.info["icc_profile"]
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
assert icc == expected_icc
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2021-01-07 16:57:49 +03:00
|
|
|
|
2021-04-10 17:58:01 +03:00
|
|
|
@mark_if_feature_version(
|
|
|
|
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
|
|
|
)
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_write_icc_metadata() -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
file_path = "Tests/images/flower2.jpg"
|
|
|
|
test_buffer = BytesIO()
|
|
|
|
with Image.open(file_path) as image:
|
|
|
|
expected_icc_profile = image.info["icc_profile"]
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
image.save(test_buffer, "webp", icc_profile=expected_icc_profile)
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
test_buffer.seek(0)
|
|
|
|
with Image.open(test_buffer) as webp_image:
|
|
|
|
webp_icc_profile = webp_image.info.get("icc_profile", None)
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
assert webp_icc_profile
|
|
|
|
if webp_icc_profile:
|
|
|
|
assert webp_icc_profile == expected_icc_profile, "Webp ICC didn't match"
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2021-01-07 16:57:49 +03:00
|
|
|
|
2021-04-10 17:58:01 +03:00
|
|
|
@mark_if_feature_version(
|
|
|
|
pytest.mark.valgrind_known_error, "libjpeg_turbo", "2.0", reason="Known Failing"
|
|
|
|
)
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_read_no_exif() -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
file_path = "Tests/images/flower.jpg"
|
|
|
|
test_buffer = BytesIO()
|
|
|
|
with Image.open(file_path) as image:
|
|
|
|
assert "exif" in image.info
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
image.save(test_buffer, "webp")
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
test_buffer.seek(0)
|
|
|
|
with Image.open(test_buffer) as webp_image:
|
2024-09-09 15:34:46 +03:00
|
|
|
assert isinstance(webp_image, WebPImagePlugin.WebPImageFile)
|
2020-02-18 16:50:34 +03:00
|
|
|
assert not webp_image._getexif()
|
2013-07-05 00:57:05 +04:00
|
|
|
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_getxmp() -> None:
|
2022-11-25 00:47:40 +03:00
|
|
|
with Image.open("Tests/images/flower.webp") as im:
|
|
|
|
assert "xmp" not in im.info
|
2024-08-23 11:48:28 +03:00
|
|
|
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 == {}
|
2022-11-25 00:47:40 +03:00
|
|
|
|
|
|
|
with Image.open("Tests/images/flower2.webp") as im:
|
|
|
|
if ElementTree is None:
|
2023-10-06 09:31:06 +03:00
|
|
|
with pytest.warns(
|
|
|
|
UserWarning,
|
|
|
|
match="XMP data cannot be read without defusedxml dependency",
|
|
|
|
):
|
2022-11-25 00:47:40 +03:00
|
|
|
assert im.getxmp() == {}
|
|
|
|
else:
|
2024-05-20 16:11:50 +03:00
|
|
|
assert "xmp" in im.info
|
2022-11-25 00:47:40 +03:00
|
|
|
assert (
|
|
|
|
im.getxmp()["xmpmeta"]["xmptk"]
|
|
|
|
== "Adobe XMP Core 5.3-c011 66.145661, 2012/02/06-14:56:27 "
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2024-01-31 12:12:58 +03:00
|
|
|
def test_write_animated_metadata(tmp_path: Path) -> None:
|
2020-02-18 16:50:34 +03:00
|
|
|
iccp_data = b"<iccp_data>"
|
|
|
|
exif_data = b"<exif_data>"
|
|
|
|
xmp_data = b"<xmp_data>"
|
2013-07-05 00:57:05 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
temp_file = str(tmp_path / "temp.webp")
|
|
|
|
with Image.open("Tests/images/anim_frame1.webp") as frame1:
|
|
|
|
with Image.open("Tests/images/anim_frame2.webp") as frame2:
|
|
|
|
frame1.save(
|
|
|
|
temp_file,
|
|
|
|
save_all=True,
|
|
|
|
append_images=[frame2, frame1, frame2],
|
|
|
|
icc_profile=iccp_data,
|
|
|
|
exif=exif_data,
|
|
|
|
xmp=xmp_data,
|
2019-06-13 18:54:11 +03:00
|
|
|
)
|
2014-01-20 22:59:30 +04:00
|
|
|
|
2020-02-18 16:50:34 +03:00
|
|
|
with Image.open(temp_file) as image:
|
|
|
|
assert "icc_profile" in image.info
|
|
|
|
assert "exif" in image.info
|
|
|
|
assert "xmp" in image.info
|
|
|
|
assert iccp_data == image.info.get("icc_profile", None)
|
|
|
|
assert exif_data == image.info.get("exif", None)
|
|
|
|
assert xmp_data == image.info.get("xmp", None)
|