Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow putpalette to accept 1024 integers to include alpha values #5089

Merged
merged 1 commit into from Dec 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 19 additions & 2 deletions Tests/test_image_putpalette.py
@@ -1,8 +1,8 @@
import pytest

from PIL import ImagePalette
from PIL import Image, ImagePalette

from .helper import hopper
from .helper import assert_image_equal, hopper


def test_putpalette():
Expand Down Expand Up @@ -39,3 +39,20 @@ def test_imagepalette():
im.putpalette(ImagePalette.random())
im.putpalette(ImagePalette.sepia())
im.putpalette(ImagePalette.wedge())


def test_putpalette_with_alpha_values():
with Image.open("Tests/images/transparent.gif") as im:
expected = im.convert("RGBA")

palette = im.getpalette()
transparency = im.info.pop("transparency")

palette_with_alpha_values = []
for i in range(256):
color = palette[i * 3 : i * 3 + 3]
alpha = 0 if i == transparency else 255
palette_with_alpha_values += color + [alpha]
im.putpalette(palette_with_alpha_values, "RGBA")

assert_image_equal(im.convert("RGBA"), expected)
26 changes: 18 additions & 8 deletions src/PIL/Image.py
Expand Up @@ -815,16 +815,24 @@ def load(self):
"""
if self.im and self.palette and self.palette.dirty:
# realize palette
self.im.putpalette(*self.palette.getdata())
mode, arr = self.palette.getdata()
if mode == "RGBA":
mode = "RGB"
self.info["transparency"] = arr[3::4]
arr = bytes(
value for (index, value) in enumerate(arr) if index % 4 != 3
)
self.im.putpalette(mode, arr)
self.palette.dirty = 0
self.palette.mode = "RGB"
self.palette.rawmode = None
if "transparency" in self.info:
if isinstance(self.info["transparency"], int):
self.im.putpalettealpha(self.info["transparency"], 0)
else:
self.im.putpalettealphas(self.info["transparency"])
self.palette.mode = "RGBA"
else:
self.palette.mode = "RGB"

if self.im:
if cffi and USE_CFFI_ACCESS:
Expand Down Expand Up @@ -1672,12 +1680,14 @@ def putdata(self, data, scale=1.0, offset=0.0):

def putpalette(self, data, rawmode="RGB"):
"""
Attaches a palette to this image. The image must be a "P",
"PA", "L" or "LA" image, and the palette sequence must contain
768 integer values, where each group of three values represent
the red, green, and blue values for the corresponding pixel
index. Instead of an integer sequence, you can use an 8-bit
string.
Attaches a palette to this image. The image must be a "P", "PA", "L"
or "LA" image.
The palette sequence must contain either 768 integer values, or 1024
integer values if alpha is included. Each group of values represents
the red, green, blue (and alpha if included) values for the
corresponding pixel index. Instead of an integer sequence, you can use
an 8-bit string.
:param data: A palette sequence (either a list or a string).
:param rawmode: The raw mode of the palette.
Expand Down