Skip to content

Commit 95c867d

Browse files
authored
Merge pull request #8286 from radarhere/xmp
2 parents 1dffc09 + be34a7d commit 95c867d

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

Tests/test_file_jpeg.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -991,6 +991,21 @@ def test_getxmp_padded(self) -> None:
991991
else:
992992
assert im.getxmp() == {"xmpmeta": None}
993993

994+
def test_save_xmp(self, tmp_path: Path) -> None:
995+
f = str(tmp_path / "temp.jpg")
996+
im = hopper()
997+
im.save(f, xmp=b"XMP test")
998+
with Image.open(f) as reloaded:
999+
assert reloaded.info["xmp"] == b"XMP test"
1000+
1001+
im.info["xmp"] = b"1" * 65504
1002+
im.save(f)
1003+
with Image.open(f) as reloaded:
1004+
assert reloaded.info["xmp"] == b"1" * 65504
1005+
1006+
with pytest.raises(ValueError):
1007+
im.save(f, xmp=b"1" * 65505)
1008+
9941009
@pytest.mark.timeout(timeout=1)
9951010
def test_eof(self) -> None:
9961011
# Even though this decoder never says that it is finished

src/PIL/JpegImagePlugin.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -747,17 +747,27 @@ def validate_qtables(
747747
extra = info.get("extra", b"")
748748

749749
MAX_BYTES_IN_MARKER = 65533
750+
xmp = info.get("xmp", im.info.get("xmp"))
751+
if xmp:
752+
overhead_len = 29 # b"http://ns.adobe.com/xap/1.0/\x00"
753+
max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
754+
if len(xmp) > max_data_bytes_in_marker:
755+
msg = "XMP data is too long"
756+
raise ValueError(msg)
757+
size = o16(2 + overhead_len + len(xmp))
758+
extra += b"\xFF\xE1" + size + b"http://ns.adobe.com/xap/1.0/\x00" + xmp
759+
750760
icc_profile = info.get("icc_profile")
751761
if icc_profile:
752-
ICC_OVERHEAD_LEN = 14
753-
MAX_DATA_BYTES_IN_MARKER = MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN
762+
overhead_len = 14 # b"ICC_PROFILE\0" + o8(i) + o8(len(markers))
763+
max_data_bytes_in_marker = MAX_BYTES_IN_MARKER - overhead_len
754764
markers = []
755765
while icc_profile:
756-
markers.append(icc_profile[:MAX_DATA_BYTES_IN_MARKER])
757-
icc_profile = icc_profile[MAX_DATA_BYTES_IN_MARKER:]
766+
markers.append(icc_profile[:max_data_bytes_in_marker])
767+
icc_profile = icc_profile[max_data_bytes_in_marker:]
758768
i = 1
759769
for marker in markers:
760-
size = o16(2 + ICC_OVERHEAD_LEN + len(marker))
770+
size = o16(2 + overhead_len + len(marker))
761771
extra += (
762772
b"\xFF\xE2"
763773
+ size

0 commit comments

Comments
 (0)