Question

Using the Python Imaging Library, I can call

img.convert("P", palette=Image.ADAPTIVE)

or

img.convert("P", palette=Image.WEB)

but is there a way to convert to an arbitrary palette?

p = []
for i in range(0, 256):
    p.append(i, 0, 0)
img.convert("P", palette=p)

where it'll map each pixel to the closest colour found in the image? Or is this supported for Image.WEB and nothing else?

Was it helpful?

Solution

While looking through the source code of convert() I saw that it references im.quantize. quantize can take a palette argument. If you provide an Image that has a palette, this function will take that palette and apply it to the image.

Example:

    src = Image.open("sourcefilewithpalette.bmp")
    new = Image.open("unconvertednew24bit.bmp")
    converted = new.quantize(palette=src)
    converted.save("converted.bmp")

The other provided answer didn't work for me (it did some really bad double palette conversion or something,) but this solution did.

OTHER TIPS

The ImagePalette module docs's first example shows how to attach a palette to an image, but that image must already be of mode "P" or "L". One can, however, adapt the example to convert a full RGB image to a palette of your choice:

from __future__ import division
import Image

palette = []
levels = 8
stepsize = 256 // levels
for i in range(256):
    v = i // stepsize * stepsize
    palette.extend((v, v, v))

assert len(palette) == 768

original_path = 'original.jpg'
original = Image.open(original_path)
converted = Image.new('P', original.size)
converted.putpalette(palette)
converted.paste(original, (0, 0))
converted.show()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top