PIL: Convert RGB image to a specific 8-bit palette?

15,238

Solution 1

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.

Solution 2

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()
Share:
15,238

Related videos on Youtube

mcccclean
Author by

mcccclean

Updated on April 25, 2022

Comments

  • mcccclean
    mcccclean about 2 years

    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?

  • Edward Falk
    Edward Falk about 9 years
    Have you tested this?
  • Mike Boers
    Mike Boers about 9 years
    I'm pretty sure I did at the time (~5 years ago). Did it not work for you?
  • Edward Falk
    Edward Falk about 9 years
    I didn't try. I wound up using im.quantize()