Skip to content

Commit

Permalink
Merge pull request #6352 from radarhere/apply_transparency
Browse files Browse the repository at this point in the history
Added apply_transparency()
  • Loading branch information
hugovk committed Jun 11, 2022
2 parents 8e37d4c + 70a060e commit 8bd7e81
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
29 changes: 29 additions & 0 deletions Tests/test_image.py
Expand Up @@ -849,6 +849,35 @@ def test_zero_tobytes(self, size):
im = Image.new("RGB", size)
assert im.tobytes() == b""

def test_apply_transparency(self):
im = Image.new("P", (1, 1))
im.putpalette((0, 0, 0, 1, 1, 1))
assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}

# Test that no transformation is applied without transparency
im.apply_transparency()
assert im.palette.colors == {(0, 0, 0): 0, (1, 1, 1): 1}

# Test that a transparency index is applied
im.info["transparency"] = 0
im.apply_transparency()
assert "transparency" not in im.info
assert im.palette.colors == {(0, 0, 0, 0): 0, (1, 1, 1, 255): 1}

# Test that existing transparency is kept
im = Image.new("P", (1, 1))
im.putpalette((0, 0, 0, 255, 1, 1, 1, 128), "RGBA")
im.info["transparency"] = 0
im.apply_transparency()
assert im.palette.colors == {(0, 0, 0, 0): 0, (1, 1, 1, 128): 1}

# Test that transparency bytes are applied
with Image.open("Tests/images/pil123p.png") as im:
assert isinstance(im.info["transparency"], bytes)
assert im.palette.colors[(27, 35, 6)] == 24
im.apply_transparency()
assert im.palette.colors[(27, 35, 6, 214)] == 24

def test_categories_deprecation(self):
with pytest.warns(DeprecationWarning):
assert hopper().category == 0
Expand Down
1 change: 1 addition & 0 deletions docs/reference/Image.rst
Expand Up @@ -123,6 +123,7 @@ methods. Unless otherwise stated, all methods return a new instance of the


.. automethod:: PIL.Image.Image.alpha_composite
.. automethod:: PIL.Image.Image.apply_transparency
.. automethod:: PIL.Image.Image.convert

The following example converts an RGB image (linearly calibrated according to
Expand Down
9 changes: 6 additions & 3 deletions docs/releasenotes/9.2.0.rst
Expand Up @@ -57,10 +57,13 @@ TODO
API Additions
=============

TODO
^^^^
Image.apply_transparency
^^^^^^^^^^^^^^^^^^^^^^^^

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

Security
========
Expand Down
22 changes: 22 additions & 0 deletions src/PIL/Image.py
Expand Up @@ -1449,6 +1449,28 @@ def getpalette(self, rawmode="RGB"):
rawmode = mode
return list(self.im.getpalette(mode, rawmode))

def apply_transparency(self):
"""
If a P mode image has a "transparency" key in the info dictionary,
remove the key and apply the transparency to the palette instead.
"""
if self.mode != "P" or "transparency" not in self.info:
return

from . import ImagePalette

palette = self.getpalette("RGBA")
transparency = self.info["transparency"]
if isinstance(transparency, bytes):
for i, alpha in enumerate(transparency):
palette[i * 4 + 3] = alpha
else:
palette[transparency * 4 + 3] = 0
self.palette = ImagePalette.ImagePalette("RGBA", bytes(palette))
self.palette.dirty = 1

del self.info["transparency"]

def getpixel(self, xy):
"""
Returns the pixel value at a given position.
Expand Down

0 comments on commit 8bd7e81

Please sign in to comment.