Merge pull request #3519 from radarhere/putpixel

Allow RGB and RGBA values for P image putpixel
This commit is contained in:
Hugo 2019-01-01 11:46:30 +02:00 committed by GitHub
commit 6b5aa006b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 30 additions and 2 deletions

View File

@ -175,6 +175,12 @@ class TestImageGetPixel(AccessTest):
self.check(mode, 2**15+1)
self.check(mode, 2**16-1)
def test_p_putpixel_rgb_rgba(self):
for color in [(255, 0, 0), (255, 0, 0, 255)]:
im = Image.new("P", (1, 1), 0)
im.putpixel((0, 0), color)
self.assertEqual(im.convert("RGB").getpixel((0, 0)), (255, 0, 0))
@unittest.skipIf(cffi is None, "No cffi")
class TestCffiPutPixel(TestImagePutPixel):
@ -294,6 +300,13 @@ class TestCffi(AccessTest):
# pixels can contain garbage if image is released
self.assertEqual(px[i, 0], 0)
def test_p_putpixel_rgb_rgba(self):
for color in [(255, 0, 0), (255, 0, 0, 255)]:
im = Image.new("P", (1, 1), 0)
access = PyAccess.new(im, False)
access.putpixel((0, 0), color)
self.assertEqual(im.convert("RGB").getpixel((0, 0)), (255, 0, 0))
class TestEmbeddable(unittest.TestCase):
@unittest.skipIf(not sys.platform.startswith('win32') or

View File

@ -65,7 +65,8 @@ Access using negative indexes is also possible.
Modifies the pixel at x,y. The color is given as a single
numerical value for single band images, and a tuple for
multi-band images
multi-band images. In addition to this, RGB and RGBA tuples
are accepted for P images.
:param xy: The pixel coordinate, given as (x, y).
:param color: The pixel value according to its mode. e.g. tuple (r, g, b) for RGB mode)

View File

@ -1651,7 +1651,8 @@ class Image(object):
"""
Modifies the pixel at the given position. The color is given as
a single numerical value for single-band images, and a tuple for
multi-band images.
multi-band images. In addition to this, RGB and RGBA tuples are
accepted for P images.
Note that this method is relatively slow. For more extensive changes,
use :py:meth:`~PIL.Image.Image.paste` or the :py:mod:`~PIL.ImageDraw`
@ -1674,6 +1675,11 @@ class Image(object):
if self.pyaccess:
return self.pyaccess.putpixel(xy, value)
if self.mode == "P" and \
isinstance(value, (list, tuple)) and len(value) in [3, 4]:
# RGB or RGBA value for a P image
value = self.palette.getcolor(value)
return self.im.putpixel(xy, value)
def remap_palette(self, dest_map, source_palette=None):

View File

@ -53,6 +53,8 @@ class PyAccess(object):
# Keep pointer to im object to prevent dereferencing.
self._im = img.im
if self._im.mode == "P":
self._palette = img.palette
# Debugging is polluting test traces, only useful here
# when hacking on PyAccess
@ -80,6 +82,12 @@ class PyAccess(object):
if y < 0:
y = self.ysize + y
(x, y) = self.check_xy((x, y))
if self._im.mode == "P" and \
isinstance(color, (list, tuple)) and len(color) in [3, 4]:
# RGB or RGBA value for a P image
color = self._palette.getcolor(color)
return self.set_pixel(x, y, color)
def __getitem__(self, xy):