PIL: конвертировать RGB-изображение в конкретную 8-битную палитру? - PullRequest
8 голосов
/ 25 июня 2010

Используя библиотеку изображений Python, я могу позвонить

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

или

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

, но есть ли способ конвертировать в произвольную палитру?

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

где он сопоставит каждый пиксель с ближайшим цветом, найденным на изображении?Или это поддерживается для Image.WEB и ничего больше?

Ответы [ 2 ]

7 голосов
/ 23 марта 2012

Просматривая исходный код convert(), я увидел, что он ссылается на im.quantize. quantize может принимать аргумент палитры. Если вы укажете изображение с палитрой, эта функция возьмет эту палитру и применит ее к изображению.

Пример:

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

Другой предоставленный ответ не сработал для меня (он сделал действительно плохое преобразование двойной палитры или что-то подобное), но это решение сработало.

2 голосов
/ 25 июня 2010

Первый пример ImagePalette модуля docs показывает, как прикрепить палитру к изображению, но это изображение должно уже иметь режим "P" или "L". Однако можно адаптировать пример для преобразования полного изображения RGB в палитру по вашему выбору:

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()
...