Skip to content

Commit 8bd7e81

Browse files
authored
Merge pull request #6352 from radarhere/apply_transparency
Added apply_transparency()
2 parents 8e37d4c + 70a060e commit 8bd7e81

File tree

4 files changed

+58
-3
lines changed

4 files changed

+58
-3
lines changed

Tests/test_image.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,35 @@ def test_zero_tobytes(self, size):
849849
im = Image.new("RGB", size)
850850
assert im.tobytes() == b""
851851

852+
def test_apply_transparency(self):
853+
im = Image.new("P", (1, 1))
854+
im.putpalette((0, 0, 0, 1, 1, 1))
855+
assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}
856+
857+
# Test that no transformation is applied without transparency
858+
im.apply_transparency()
859+
assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}
860+
861+
# Test that a transparency index is applied
862+
im.info["transparency"] = 0
863+
im.apply_transparency()
864+
assert "transparency" not in im.info
865+
assert im.palette.colors == {(0, 0, 0, 0): 0, (1, 1, 1, 255): 1}
866+
867+
# Test that existing transparency is kept
868+
im = Image.new("P", (1, 1))
869+
im.putpalette((0, 0, 0, 255, 1, 1, 1, 128), "RGBA")
870+
im.info["transparency"] = 0
871+
im.apply_transparency()
872+
assert im.palette.colors == {(0, 0, 0, 0): 0, (1, 1, 1, 128): 1}
873+
874+
# Test that transparency bytes are applied
875+
with Image.open("Tests/images/pil123p.png") as im:
876+
assert isinstance(im.info["transparency"], bytes)
877+
assert im.palette.colors[(27, 35, 6)] == 24
878+
im.apply_transparency()
879+
assert im.palette.colors[(27, 35, 6, 214)] == 24
880+
852881
def test_categories_deprecation(self):
853882
with pytest.warns(DeprecationWarning):
854883
assert hopper().category == 0

docs/reference/Image.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ methods. Unless otherwise stated, all methods return a new instance of the
123123

124124

125125
.. automethod:: PIL.Image.Image.alpha_composite
126+
.. automethod:: PIL.Image.Image.apply_transparency
126127
.. automethod:: PIL.Image.Image.convert
127128

128129
The following example converts an RGB image (linearly calibrated according to

docs/releasenotes/9.2.0.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,13 @@ TODO
5757
API Additions
5858
=============
5959

60-
TODO
61-
^^^^
60+
Image.apply_transparency
61+
^^^^^^^^^^^^^^^^^^^^^^^^
6262

63-
TODO
63+
Added :py:meth:`~PIL.Image.Image.apply_transparency`, a method to take a P mode image
64+
with "transparency" in ``im.info``, and apply the transparency to the palette instead.
65+
The image's palette mode will become "RGBA", and "transparency" will be removed from
66+
``im.info``.
6467

6568
Security
6669
========

src/PIL/Image.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,6 +1449,28 @@ def getpalette(self, rawmode="RGB"):
14491449
rawmode = mode
14501450
return list(self.im.getpalette(mode, rawmode))
14511451

1452+
def apply_transparency(self):
1453+
"""
1454+
If a P mode image has a "transparency" key in the info dictionary,
1455+
remove the key and apply the transparency to the palette instead.
1456+
"""
1457+
if self.mode != "P" or "transparency" not in self.info:
1458+
return
1459+
1460+
from . import ImagePalette
1461+
1462+
palette = self.getpalette("RGBA")
1463+
transparency = self.info["transparency"]
1464+
if isinstance(transparency, bytes):
1465+
for i, alpha in enumerate(transparency):
1466+
palette[i * 4 + 3] = alpha
1467+
else:
1468+
palette[transparency * 4 + 3] = 0
1469+
self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
1470+
self.palette.dirty = 1
1471+
1472+
del self.info["transparency"]
1473+
14521474
def getpixel(self, xy):
14531475
"""
14541476
Returns the pixel value at a given position.

0 commit comments

Comments
 (0)