PIL:将RGB图像转换为特定8位调色板?

12 投票
2 回答
17795 浏览
提问于 2025-04-16 00:25

我可以使用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 个回答

3

ImagePalette模块的文档中第一个例子展示了如何将调色板附加到一张图片上,但这张图片必须已经是“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()
9

在查看convert()的源代码时,我发现它提到了im.quantizequantize这个函数可以接受一个调色板参数。如果你提供一个有调色板的图像,这个函数就会把那个调色板应用到图像上。

举个例子:

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

之前提供的答案对我没用(它做了一些很糟糕的双重调色板转换之类的),但这个解决方案有效。

撰写回答