mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-05 06:00:58 +03:00
When allocating a new color, repurpose an unused index if necessary
This commit is contained in:
parent
f3451aefc6
commit
fa559277fb
|
@ -760,7 +760,7 @@ def _get_background(im, infoBackground):
|
||||||
# WebPImagePlugin stores an RGBA value in info["background"]
|
# WebPImagePlugin stores an RGBA value in info["background"]
|
||||||
# So it must be converted to the same format as GifImagePlugin's
|
# So it must be converted to the same format as GifImagePlugin's
|
||||||
# info["background"] - a global color table index
|
# info["background"] - a global color table index
|
||||||
background = im.palette.getcolor(background)
|
background = im.palette.getcolor(background, im)
|
||||||
return background
|
return background
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -978,7 +978,7 @@ class Image:
|
||||||
trns_im.putpalette(self.palette)
|
trns_im.putpalette(self.palette)
|
||||||
if isinstance(t, tuple):
|
if isinstance(t, tuple):
|
||||||
try:
|
try:
|
||||||
t = trns_im.palette.getcolor(t)
|
t = trns_im.palette.getcolor(t, self)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Couldn't allocate a palette color for transparency"
|
"Couldn't allocate a palette color for transparency"
|
||||||
|
@ -1016,7 +1016,7 @@ class Image:
|
||||||
del new.info["transparency"]
|
del new.info["transparency"]
|
||||||
if trns is not None:
|
if trns is not None:
|
||||||
try:
|
try:
|
||||||
new.info["transparency"] = new.palette.getcolor(trns)
|
new.info["transparency"] = new.palette.getcolor(trns, new)
|
||||||
except Exception:
|
except Exception:
|
||||||
# if we can't make a transparent color, don't leave the old
|
# if we can't make a transparent color, don't leave the old
|
||||||
# transparency hanging around to mess us up.
|
# transparency hanging around to mess us up.
|
||||||
|
@ -1049,7 +1049,7 @@ class Image:
|
||||||
if trns is not None:
|
if trns is not None:
|
||||||
if new_im.mode == "P":
|
if new_im.mode == "P":
|
||||||
try:
|
try:
|
||||||
new_im.info["transparency"] = new_im.palette.getcolor(trns)
|
new_im.info["transparency"] = new_im.palette.getcolor(trns, new_im)
|
||||||
except Exception:
|
except Exception:
|
||||||
del new_im.info["transparency"]
|
del new_im.info["transparency"]
|
||||||
warnings.warn("Couldn't allocate palette entry for transparency")
|
warnings.warn("Couldn't allocate palette entry for transparency")
|
||||||
|
@ -1764,7 +1764,7 @@ class Image:
|
||||||
and len(value) in [3, 4]
|
and len(value) in [3, 4]
|
||||||
):
|
):
|
||||||
# RGB or RGBA value for a P image
|
# RGB or RGBA value for a P image
|
||||||
value = self.palette.getcolor(value)
|
value = self.palette.getcolor(value, self)
|
||||||
return self.im.putpixel(xy, value)
|
return self.im.putpixel(xy, value)
|
||||||
|
|
||||||
def remap_palette(self, dest_map, source_palette=None):
|
def remap_palette(self, dest_map, source_palette=None):
|
||||||
|
|
|
@ -70,6 +70,7 @@ class ImageDraw:
|
||||||
self.palette = im.palette
|
self.palette = im.palette
|
||||||
else:
|
else:
|
||||||
self.palette = None
|
self.palette = None
|
||||||
|
self._image = im
|
||||||
self.im = im.im
|
self.im = im.im
|
||||||
self.draw = Image.core.draw(self.im, blend)
|
self.draw = Image.core.draw(self.im, blend)
|
||||||
self.mode = mode
|
self.mode = mode
|
||||||
|
@ -108,13 +109,13 @@ class ImageDraw:
|
||||||
if isinstance(ink, str):
|
if isinstance(ink, str):
|
||||||
ink = ImageColor.getcolor(ink, self.mode)
|
ink = ImageColor.getcolor(ink, self.mode)
|
||||||
if self.palette and not isinstance(ink, numbers.Number):
|
if self.palette and not isinstance(ink, numbers.Number):
|
||||||
ink = self.palette.getcolor(ink)
|
ink = self.palette.getcolor(ink, self._image)
|
||||||
ink = self.draw.draw_ink(ink)
|
ink = self.draw.draw_ink(ink)
|
||||||
if fill is not None:
|
if fill is not None:
|
||||||
if isinstance(fill, str):
|
if isinstance(fill, str):
|
||||||
fill = ImageColor.getcolor(fill, self.mode)
|
fill = ImageColor.getcolor(fill, self.mode)
|
||||||
if self.palette and not isinstance(fill, numbers.Number):
|
if self.palette and not isinstance(fill, numbers.Number):
|
||||||
fill = self.palette.getcolor(fill)
|
fill = self.palette.getcolor(fill, self._image)
|
||||||
fill = self.draw.draw_ink(fill)
|
fill = self.draw.draw_ink(fill)
|
||||||
return ink, fill
|
return ink, fill
|
||||||
|
|
||||||
|
|
|
@ -97,7 +97,7 @@ class ImagePalette:
|
||||||
# Declare tostring as an alias for tobytes
|
# Declare tostring as an alias for tobytes
|
||||||
tostring = tobytes
|
tostring = tobytes
|
||||||
|
|
||||||
def getcolor(self, color):
|
def getcolor(self, color, image=None):
|
||||||
"""Given an rgb tuple, allocate palette entry.
|
"""Given an rgb tuple, allocate palette entry.
|
||||||
|
|
||||||
.. warning:: This method is experimental.
|
.. warning:: This method is experimental.
|
||||||
|
@ -119,7 +119,14 @@ class ImagePalette:
|
||||||
self._palette = bytearray(self.palette)
|
self._palette = bytearray(self.palette)
|
||||||
index = len(self.palette) // 3
|
index = len(self.palette) // 3
|
||||||
if index >= 256:
|
if index >= 256:
|
||||||
raise ValueError("cannot allocate more than 256 colors") from e
|
if image:
|
||||||
|
# Search for an unused index
|
||||||
|
for i, count in reversed(list(enumerate(image.histogram()))):
|
||||||
|
if count == 0:
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
if index >= 256:
|
||||||
|
raise ValueError("cannot allocate more than 256 colors") from e
|
||||||
self.colors[color] = index
|
self.colors[color] = index
|
||||||
if index * 3 < len(self.palette):
|
if index * 3 < len(self.palette):
|
||||||
self._palette[index * 3] = color[0]
|
self._palette[index * 3] = color[0]
|
||||||
|
|
|
@ -54,6 +54,7 @@ class PyAccess:
|
||||||
self.image32 = ffi.cast("int **", vals["image32"])
|
self.image32 = ffi.cast("int **", vals["image32"])
|
||||||
self.image = ffi.cast("unsigned char **", vals["image"])
|
self.image = ffi.cast("unsigned char **", vals["image"])
|
||||||
self.xsize, self.ysize = img.im.size
|
self.xsize, self.ysize = img.im.size
|
||||||
|
self._img = img
|
||||||
|
|
||||||
# Keep pointer to im object to prevent dereferencing.
|
# Keep pointer to im object to prevent dereferencing.
|
||||||
self._im = img.im
|
self._im = img.im
|
||||||
|
@ -93,7 +94,7 @@ class PyAccess:
|
||||||
and len(color) in [3, 4]
|
and len(color) in [3, 4]
|
||||||
):
|
):
|
||||||
# RGB or RGBA value for a P image
|
# RGB or RGBA value for a P image
|
||||||
color = self._palette.getcolor(color)
|
color = self._palette.getcolor(color, self._img)
|
||||||
|
|
||||||
return self.set_pixel(x, y, color)
|
return self.set_pixel(x, y, color)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user