【发布时间】:2015-06-08 14:32:27
【问题描述】:
我正在尝试使用 Pillow 库(Python 图像库,PIL)将 PNG 格式的 RGB 图像转换为使用特定的索引调色板。但我想使用“四舍五入到最接近的颜色”方法进行转换,而不是抖动,因为图像是像素艺术,抖动会扭曲区域的轮廓并给原本应该是平坦的区域添加噪点。
我试过Image.Image.paste(),它使用了四种指定的颜色,但它产生了一个抖动的图像:
from PIL import Image
oldimage = Image.open("oldimage.png")
palettedata = [0, 0, 0, 102, 102, 102, 176, 176, 176, 255, 255, 255]
newimage = Image.new('P', oldimage.size)
newimage.putpalette(palettedata * 64)
newimage.paste(oldimage, (0, 0) + oldimage.size)
newimage.show()
我尝试了pictu's answer to a similar question 中提到的Image.Image.quantize(),但它也产生了抖动:
from PIL import Image
palettedata = [0, 0, 0, 102, 102, 102, 176, 176, 176, 255, 255, 255]
palimage = Image.new('P', (16, 16))
palimage.putpalette(palettedata * 64)
oldimage = Image.open("School_scrollable1.png")
newimage = oldimage.quantize(palette=palimage)
newimage.show()
我试过Image.Image.convert(),它在没有抖动的情况下转换了图像,但它包含了指定颜色以外的颜色,大概是因为它使用了网络调色板或自适应调色板
from PIL import Image
oldimage = Image.open("oldimage.png")
palettedata = [0, 0, 0, 102, 102, 102, 176, 176, 176, 255, 255, 255]
expanded_palettedata = palettedata * 64
newimage = oldimage.convert('P', dither=Image.NONE, palette=palettedata)
newimage.show()
如何在不抖动的情况下自动将图像转换为特定调色板?我想避免使用在 Python 中处理每个单独像素的解决方案,如 John La Rooy's answer 和 cmets 中所建议的那样,因为我之前的解决方案涉及用 Python 编写的内部循环已被证明对于大图像来说明显很慢。
【问题讨论】:
-
给定任意调色板的“四舍五入到最接近的颜色”几乎需要逐像素技术,因此最好用 C 等非解释性语言编写。部分 PIL 是编写的在 C 中——它的开源——所以你可以扩展它而不是从头开始编写一个全新的扩展模块。
-
@martineau 抖动到自定义调色板也需要逐像素技术,但 PIL 可以做到。在网络或自适应调色板中四舍五入到最接近的颜色也需要逐像素技术,但 PIL 可以做到。它只是无法在自定义调色板中四舍五入到最接近的颜色。如果我要分叉 PIL,我将不得不为每个平台购买一台机器,以便为每个平台维护分叉的二进制文件。
-
PIL 可能在其中用 C 编写的部分中完成了大部分或所有这些事情。您不必正式分叉它,只需获取当前源并制作它的自定义版本适用于您正在使用的平台。
-
@martineau 在您自己的帐户中复制当前资源的 GitHub 操作称为“fork”。
标签: python image python-imaging-library