Skip to content

Commit f218169

Browse files
committed
Allow ImageMagick zTXt chunks to be extracted after copy()
1 parent 1e63f77 commit f218169

3 files changed

Lines changed: 37 additions & 42 deletions

File tree

Tests/test_file_png.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -591,19 +591,23 @@ def test_textual_chunks_after_idat(self):
591591
with Image.open("Tests/images/hopper_idat_after_image_end.png") as im:
592592
assert im.text == {"TXT": "VALUE", "ZIP": "VALUE"}
593593

594-
@pytest.mark.parametrize(
595-
"test_file",
596-
[
597-
"Tests/images/exif.png", # With an EXIF chunk
598-
"Tests/images/exif_imagemagick.png", # With an ImageMagick zTXt chunk
599-
],
600-
)
601-
def test_exif(self, test_file):
602-
with Image.open(test_file) as im:
594+
def test_exif(self):
595+
# With an EXIF chunk
596+
with Image.open("Tests/images/exif.png") as im:
603597
exif = im._getexif()
604598
assert exif[274] == 1
605599

606-
def test_xmp_tags_orientation(self):
600+
# With an ImageMagick zTXt chunk
601+
with Image.open("Tests/images/exif_imagemagick.png") as im:
602+
exif = im._getexif()
603+
assert exif[274] == 1
604+
605+
# Assert that info still can be extracted
606+
# when the image is no longer a PngImageFile instance
607+
exif = im.copy().getexif()
608+
assert exif[274] == 1
609+
610+
# With XMP tags
607611
with Image.open("Tests/images/xmp_tags_orientation.png") as im:
608612
exif = im.getexif()
609613
assert exif[274] == 3

src/PIL/Image.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,30 +1298,31 @@ def getextrema(self):
12981298
return tuple(extrema)
12991299
return self.im.getextrema()
13001300

1301-
def _parse_xmp_tags(self):
1302-
if 0x0112 in self._exif:
1303-
return
1304-
1305-
xmp_tags = self.info.get("XML:com.adobe.xmp")
1306-
if not xmp_tags:
1307-
return
1308-
1309-
root = xml.etree.ElementTree.fromstring(xmp_tags)
1310-
for elem in root.iter():
1311-
if elem.tag.endswith("}Description"):
1312-
break
1313-
else:
1314-
return
1315-
1316-
orientation = elem.attrib.get("{http://ns.adobe.com/tiff/1.0/}Orientation")
1317-
if orientation:
1318-
self._exif[0x0112] = int(orientation)
1319-
13201301
def getexif(self):
13211302
if self._exif is None:
13221303
self._exif = Exif()
1323-
self._exif.load(self.info.get("exif"))
1324-
self._parse_xmp_tags()
1304+
1305+
exif_info = self.info.get("exif")
1306+
if exif_info is None and "Raw profile type exif" in self.info:
1307+
exif_info = bytes.fromhex(
1308+
"".join(self.info["Raw profile type exif"].split("\n")[3:])
1309+
)
1310+
self._exif.load(exif_info)
1311+
1312+
# XMP tags
1313+
if 0x0112 not in self._exif:
1314+
xmp_tags = self.info.get("XML:com.adobe.xmp")
1315+
if xmp_tags:
1316+
root = xml.etree.ElementTree.fromstring(xmp_tags)
1317+
for elem in root.iter():
1318+
if elem.tag.endswith("}Description"):
1319+
orientation = elem.attrib.get(
1320+
"{http://ns.adobe.com/tiff/1.0/}Orientation"
1321+
)
1322+
if orientation:
1323+
self._exif[0x0112] = int(orientation)
1324+
break
1325+
13251326
return self._exif
13261327

13271328
def getim(self):

src/PIL/PngImagePlugin.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -931,17 +931,7 @@ def getexif(self):
931931
if "exif" not in self.info:
932932
self.load()
933933

934-
if self._exif is None:
935-
self._exif = Image.Exif()
936-
937-
exif_info = self.info.get("exif")
938-
if exif_info is None and "Raw profile type exif" in self.info:
939-
exif_info = bytes.fromhex(
940-
"".join(self.info["Raw profile type exif"].split("\n")[3:])
941-
)
942-
self._exif.load(exif_info)
943-
self._parse_xmp_tags()
944-
return self._exif
934+
return super().getexif()
945935

946936
def _close__fp(self):
947937
try:

0 commit comments

Comments
 (0)