Skip to content

Commit de053fb

Browse files
authored
Handle XMP data from an UNDEFINED TIFF tag (#8997)
2 parents 36cea19 + f03c236 commit de053fb

4 files changed

Lines changed: 30 additions & 3 deletions

File tree

Tests/test_file_tiff.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
ImageFile,
1515
JpegImagePlugin,
1616
TiffImagePlugin,
17+
TiffTags,
1718
UnidentifiedImageError,
1819
)
1920
from PIL.TiffImagePlugin import RESOLUTION_UNIT, X_RESOLUTION, Y_RESOLUTION
@@ -900,6 +901,29 @@ def test_getxmp(self) -> None:
900901
assert description[0]["format"] == "image/tiff"
901902
assert description[3]["BitsPerSample"]["Seq"]["li"] == ["8", "8", "8"]
902903

904+
def test_getxmp_undefined(self, tmp_path: Path) -> None:
905+
tmpfile = tmp_path / "temp.tif"
906+
im = Image.new("L", (1, 1))
907+
ifd = TiffImagePlugin.ImageFileDirectory_v2()
908+
ifd.tagtype[700] = TiffTags.UNDEFINED
909+
with Image.open("Tests/images/lab.tif") as im_xmp:
910+
ifd[700] = im_xmp.info["xmp"]
911+
im.save(tmpfile, tiffinfo=ifd)
912+
913+
with Image.open(tmpfile) as im_reloaded:
914+
if ElementTree is None:
915+
with pytest.warns(
916+
UserWarning,
917+
match="XMP data cannot be read without defusedxml dependency",
918+
):
919+
assert im_reloaded.getxmp() == {}
920+
else:
921+
assert "xmp" in im_reloaded.info
922+
xmp = im_reloaded.getxmp()
923+
924+
description = xmp["xmpmeta"]["RDF"]["Description"]
925+
assert description[0]["format"] == "image/tiff"
926+
903927
def test_get_photoshop_blocks(self) -> None:
904928
with Image.open("Tests/images/lab.tif") as im:
905929
assert isinstance(im, TiffImagePlugin.TiffImageFile)

Tests/test_image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,7 +995,7 @@ def test_getxmp_padded(self) -> None:
995995
im = Image.new("RGB", (1, 1))
996996
im.info["xmp"] = (
997997
b'<?xpacket begin="\xef\xbb\xbf" id="W5M0MpCehiHzreSzNTczkc9d"?>\n'
998-
b'<x:xmpmeta xmlns:x="adobe:ns:meta/" />\n<?xpacket end="w"?>\x00\x00'
998+
b'<x:xmpmeta xmlns:x="adobe:ns:meta/" />\n<?xpacket end="w"?>\x00\x00 '
999999
)
10001000
if ElementTree is None:
10011001
with pytest.warns(

src/PIL/Image.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,7 +1511,7 @@ def get_value(element: Element) -> str | dict[str, Any] | None:
15111511
return {}
15121512
if "xmp" not in self.info:
15131513
return {}
1514-
root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00"))
1514+
root = ElementTree.fromstring(self.info["xmp"].rstrip(b"\x00 "))
15151515
return {get_name(root.tag): get_value(root)}
15161516

15171517
def getexif(self) -> Exif:

src/PIL/TiffImagePlugin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,10 @@ def _seek(self, frame: int) -> None:
12601260
self.fp.seek(self._frame_pos[frame])
12611261
self.tag_v2.load(self.fp)
12621262
if XMP in self.tag_v2:
1263-
self.info["xmp"] = self.tag_v2[XMP]
1263+
xmp = self.tag_v2[XMP]
1264+
if isinstance(xmp, tuple) and len(xmp) == 1:
1265+
xmp = xmp[0]
1266+
self.info["xmp"] = xmp
12641267
elif "xmp" in self.info:
12651268
del self.info["xmp"]
12661269
self._reload_exif()

0 commit comments

Comments
 (0)