From a666c91e10d3d4922b2eefe3c31dbeb970baa8d6 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Sat, 12 Dec 2020 14:12:30 +1100 Subject: [PATCH] Allow putpalette to accept 1024 integers to include alpha values --- Tests/test_image_putpalette.py | 21 +++++++++++++++++++-- src/PIL/Image.py | 26 ++++++++++++++++++-------- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/Tests/test_image_putpalette.py b/Tests/test_image_putpalette.py index 32f8de2c0ae..5a9df11b1db 100644 --- a/Tests/test_image_putpalette.py +++ b/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(): @@ -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) diff --git a/src/PIL/Image.py b/src/PIL/Image.py index ae2559d11de..55861a75af0 100644 --- a/src/PIL/Image.py +++ b/src/PIL/Image.py @@ -815,9 +815,15 @@ 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): @@ -825,6 +831,8 @@ def load(self): 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: @@ -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.