Skip to content

Commit 3a61c9e

Browse files
authored
Merge pull request #6350 from radarhere/remap_rgba_palette
2 parents 3558207 + 4c8aff9 commit 3a61c9e

File tree

2 files changed

+28
-8
lines changed

2 files changed

+28
-8
lines changed

Tests/test_image.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,15 @@ def test_remap_palette(self):
604604
with Image.open("Tests/images/hopper.gif") as im:
605605
assert_image_equal(im, im.remap_palette(list(range(256))))
606606

607+
# Test identity transform with an RGBA palette
608+
im = Image.new("P", (256, 1))
609+
for x in range(256):
610+
im.putpixel((x, 0), x)
611+
im.putpalette(list(range(256)) * 4, "RGBA")
612+
im_remapped = im.remap_palette(list(range(256)))
613+
assert_image_equal(im, im_remapped)
614+
assert im.palette.palette == im_remapped.palette.palette
615+
607616
# Test illegal image mode
608617
with hopper() as im:
609618
with pytest.raises(ValueError):

src/PIL/Image.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,10 +1867,15 @@ def remap_palette(self, dest_map, source_palette=None):
18671867
if self.mode not in ("L", "P"):
18681868
raise ValueError("illegal image mode")
18691869

1870+
bands = 3
1871+
palette_mode = "RGB"
18701872
if source_palette is None:
18711873
if self.mode == "P":
18721874
self.load()
1873-
source_palette = self.im.getpalette("RGB")[:768]
1875+
palette_mode = self.im.getpalettemode()
1876+
if palette_mode == "RGBA":
1877+
bands = 4
1878+
source_palette = self.im.getpalette(palette_mode, palette_mode)
18741879
else: # L-mode
18751880
source_palette = bytearray(i // 3 for i in range(768))
18761881

@@ -1879,7 +1884,9 @@ def remap_palette(self, dest_map, source_palette=None):
18791884

18801885
# pick only the used colors from the palette
18811886
for i, oldPosition in enumerate(dest_map):
1882-
palette_bytes += source_palette[oldPosition * 3 : oldPosition * 3 + 3]
1887+
palette_bytes += source_palette[
1888+
oldPosition * bands : oldPosition * bands + bands
1889+
]
18831890
new_positions[oldPosition] = i
18841891

18851892
# replace the palette color id of all pixel with the new id
@@ -1905,19 +1912,23 @@ def remap_palette(self, dest_map, source_palette=None):
19051912
m_im = self.copy()
19061913
m_im.mode = "P"
19071914

1908-
m_im.palette = ImagePalette.ImagePalette("RGB", palette=mapping_palette * 3)
1915+
m_im.palette = ImagePalette.ImagePalette(
1916+
palette_mode, palette=mapping_palette * bands
1917+
)
19091918
# possibly set palette dirty, then
19101919
# m_im.putpalette(mapping_palette, 'L') # converts to 'P'
19111920
# or just force it.
19121921
# UNDONE -- this is part of the general issue with palettes
1913-
m_im.im.putpalette("RGB;L", m_im.palette.tobytes())
1922+
m_im.im.putpalette(palette_mode + ";L", m_im.palette.tobytes())
19141923

19151924
m_im = m_im.convert("L")
19161925

1917-
# Internally, we require 768 bytes for a palette.
1918-
new_palette_bytes = palette_bytes + (768 - len(palette_bytes)) * b"\x00"
1919-
m_im.putpalette(new_palette_bytes)
1920-
m_im.palette = ImagePalette.ImagePalette("RGB", palette=palette_bytes)
1926+
# Internally, we require 256 palette entries.
1927+
new_palette_bytes = (
1928+
palette_bytes + ((256 * bands) - len(palette_bytes)) * b"\x00"
1929+
)
1930+
m_im.putpalette(new_palette_bytes, palette_mode)
1931+
m_im.palette = ImagePalette.ImagePalette(palette_mode, palette=palette_bytes)
19211932

19221933
if "transparency" in self.info:
19231934
try:

0 commit comments

Comments
 (0)