Skip to content

Commit e58c673

Browse files
committed
Raise error if transparency is incorrect type or length when saving
1 parent 7f68dec commit e58c673

2 files changed

Lines changed: 52 additions & 7 deletions

File tree

Tests/test_file_png.py

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,9 @@ def test_trns_rgb(self) -> None:
502502
im = roundtrip(im)
503503
assert im.info["transparency"] == (248, 248, 248)
504504

505-
im = roundtrip(im, transparency=(0, 1, 2))
506-
assert im.info["transparency"] == (0, 1, 2)
505+
for transparency in ((0, 1, 2), [0, 1, 2]):
506+
im = roundtrip(im, transparency=transparency)
507+
assert im.info["transparency"] == (0, 1, 2)
507508

508509
def test_trns_p(self, tmp_path: Path) -> None:
509510
# Check writing a transparency of 0, issue #528
@@ -518,6 +519,36 @@ def test_trns_p(self, tmp_path: Path) -> None:
518519

519520
assert_image_equal(im2.convert("RGBA"), im.convert("RGBA"))
520521

522+
def test_trns_invalid(self, tmp_path: Path) -> None:
523+
out = tmp_path / "temp.png"
524+
525+
for mode in ("1", "L", "I;16"):
526+
im = Image.new(mode, (1, 1))
527+
with pytest.raises(
528+
ValueError, match=f"transparency for {mode} must be an integer"
529+
):
530+
im.save(out, transparency="invalid")
531+
532+
im = Image.new("I", (1, 1))
533+
with pytest.warns(DeprecationWarning, match="Saving I mode images as PNG"):
534+
with pytest.raises(ValueError):
535+
im.save(out, transparency="invalid")
536+
537+
im = Image.new("P", (1, 1))
538+
with pytest.raises(
539+
ValueError, match="transparency for P must be an integer or bytes"
540+
):
541+
im.save(out, transparency="invalid")
542+
543+
im = Image.new("RGB", (1, 1))
544+
with pytest.raises(
545+
ValueError, match="transparency for RGB must be list or tuple"
546+
):
547+
im.save(out, transparency="invalid")
548+
549+
with pytest.raises(ValueError, match="transparency for RGB must have length 3"):
550+
im.save(out, transparency=(1, 2))
551+
521552
def test_trns_null(self) -> None:
522553
# Check reading images with null tRNS value, issue #1239
523554
test_file = "Tests/images/tRNS_null_1x1.png"

src/PIL/PngImagePlugin.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,16 +1451,30 @@ def _save(
14511451
alpha_bytes = colors
14521452
if isinstance(transparency, bytes):
14531453
chunk(fp, b"tRNS", transparency[:alpha_bytes])
1454-
else:
1454+
elif isinstance(transparency, int):
14551455
transparency = max(0, min(255, transparency))
14561456
alpha = b"\xff" * transparency + b"\0"
14571457
chunk(fp, b"tRNS", alpha[:alpha_bytes])
1458+
else:
1459+
msg = "transparency for P must be an integer or bytes"
1460+
raise ValueError(msg)
14581461
elif im.mode in ("1", "L", "I", "I;16"):
1459-
transparency = max(0, min(65535, transparency))
1460-
chunk(fp, b"tRNS", o16(transparency))
1462+
if isinstance(transparency, int):
1463+
transparency = max(0, min(65535, transparency))
1464+
chunk(fp, b"tRNS", o16(transparency))
1465+
else:
1466+
msg = f"transparency for {im.mode} must be an integer"
1467+
raise ValueError(msg)
14611468
elif im.mode == "RGB":
1462-
red, green, blue = transparency
1463-
chunk(fp, b"tRNS", o16(red) + o16(green) + o16(blue))
1469+
if not isinstance(transparency, (list, tuple)):
1470+
msg = "transparency for RGB must be list or tuple"
1471+
raise ValueError(msg)
1472+
elif len(transparency) != 3:
1473+
msg = "transparency for RGB must have length 3"
1474+
raise ValueError(msg)
1475+
else:
1476+
red, green, blue = transparency
1477+
chunk(fp, b"tRNS", o16(red) + o16(green) + o16(blue))
14641478
elif im.encoderinfo.get("transparency") is not None:
14651479
# don't bother with transparency if it's an RGBA
14661480
# and it's in the info dict. It's probably just stale.

0 commit comments

Comments
 (0)