diff --git a/Tests/test_file_jpeg.py b/Tests/test_file_jpeg.py index ab799c13fb7..2015e3decd5 100644 --- a/Tests/test_file_jpeg.py +++ b/Tests/test_file_jpeg.py @@ -837,7 +837,16 @@ def test_getxmp(self): xmp = im.getxmp() assert isinstance(xmp, dict) - assert xmp["Description"]["Version"] == "10.4" + + description = xmp["xmpmeta"]["RDF"]["Description"] + assert description["DerivedFrom"] is None + assert ( + description["Look"]["Description"]["Group"]["Alt"]["li"] == "Profiles" + ) + assert description["ToneCurve"]["Seq"]["li"] == ["0, 0", "255, 255"] + + # Attribute + assert description["Version"] == "10.4" @pytest.mark.skipif(not is_win32(), reason="Windows only") diff --git a/src/PIL/JpegImagePlugin.py b/src/PIL/JpegImagePlugin.py index f449a2dc0e0..4b4926aa398 100644 --- a/src/PIL/JpegImagePlugin.py +++ b/src/PIL/JpegImagePlugin.py @@ -489,12 +489,29 @@ def getxmp(self): if segment == "APP1": marker, xmp_tags = content.rsplit(b"\x00", 1) if marker == b"http://ns.adobe.com/xap/1.0/": + + def get_name(tag): + return tag.split("}")[1] + + def get_value(element): + children = list(element) + if children: + value = {get_name(k): v for k, v in element.attrib.items()} + for child in children: + name = get_name(child.tag) + child_value = get_value(child) + if name in value: + if not isinstance(value[name], list): + value[name] = [value[name]] + value[name].append(child_value) + else: + value[name] = child_value + return value + else: + return element.text + root = xml.etree.ElementTree.fromstring(xmp_tags) - for element in root.findall(".//"): - self._xmp[element.tag.split("}")[1]] = { - child.split("}")[1]: value - for child, value in element.attrib.items() - } + self._xmp[get_name(root.tag)] = get_value(root) return self._xmp