PIL - 需要抖动,但限制调色板会导致问题

时间:2012-09-28 18:33:28

标签: python image python-imaging-library dithering

我是Python新手,并尝试使用PIL执行Arduino项目所需的解析任务。这个问题与Image.convert()方法以及调色板,抖动等选项有关。

我有一些硬件能够一次显示只有16种颜色的图像(但它们可以指定RGB三元组)。因此,我想自动执行任意色彩PNG图像的任务,选择“最佳”16色调色板来表示它,并将图像转换为仅包含16种颜色的调色图像。

我想使用抖动。问题是,image.convert()方法似乎有点时髦。它的论点没有完整记录(PIL documentation for Image.convert())所以我不知道这是我的错还是方法是错误的。

我的代码的简单版本如下:

import Image
MyImageTrueColor = Image.new('RGB',100,100) # or whatever dimension...

# I paste some images from several other PNG files in using MyImageTrueColor.paste()

MyImageDithered = MyImageTrueColor.convert(mode='P',
    colors=16,
    dither=1
    )

基于我做过的一些搜索(例如:How to reduce color palette with PIL)我会认为这种方法应该做我想要的,但没有运气。它会抖动图像,但会产生超过16种颜色的图像。

为了确保,我删除了“dither”参数。相同的输出。

我重新添加了“dither = 1”参数并抛出了Image.ADAPTIVE参数(如上面的链接所示),只是为了看看发生了什么。这导致图像包含16种颜色,但没有抖动。

我在这里遗漏了什么吗?是PIL车吗?我想出的解决方案是执行两个步骤,但这似乎是草率和不必要的。我想弄清楚如何做到这一点:-)为了完整性,这里是我的代码版本,产生正确的结果 - 但它以一种草率的方式做到了。 (第一步产生带有> 16种颜色的抖动图像,第二步产生仅包含16种颜色的图像。)

MyImage_intermediate = MyImageTrueColor.convert(mode='P',
    colors=16
    )
MyImageDithered = MyImage_intermediate.convert(mode='P',
    colors=16,
    dither=1,
    palette=Image.ADAPTIVE
    )

谢谢!

1 个答案:

答案 0 :(得分:6)

嗯,你没有正确地调用东西,所以它不应该正常工作......但即使我们正确地调用了东西,我也不确定它是否会起作用。

首先,"官方"免费版的PIL手册既不完整又过时; http://effbot.org/imagingbook/image.htm的草稿版本不完整且已过时。

  

im.convert(“P”,**选项)⇒图像

     

相同,但在将“RGB”图像转换为时,可提供更好的控制   8位调色板图像。可用选项包括:

     

抖动=。控制抖动。默认值为FLOYDSTEINBERG,即   将错误分配给相邻像素。要禁用抖动,请使用   NONE。

     

调色板=。控制调色板生成。默认为WEB,即   标准的216色“网页调色板”。要使用优化的调色板,请使用   自适应的。

     

颜色=。控制调色板时使用的颜色数   调色板是自适应的。默认为最大值,256色。

所以,首先,你不能在没有colors的情况下使用ADAPTIVE - 原因显而易见:唯一的另一个选择是WEB,只处理固定的216色调色板

其次,您无法将1传递给dither。如果恰好是FLOYDSTEINBERG的价值,那可能会有效,但那是3。所以,你传递了一个没有证件的价值;谁知道会怎么做?特别是因为,查看所有听起来像抖动算法可能名称的常量,它们都没有值1。

因此,您可以尝试将其更改为dither=Image.FLOYDSTEINBERG(以及palette=Image.ADAPTIVE)并查看是否会产生影响。

但是,看看代码,看起来这样做不会有任何好处:

if mode == "P" and palette == ADAPTIVE:
    im = self.im.quantize(colors)
    return self._new(im)

这是在我们到达抖动代码之前发生的。所以它与调用(现在已弃用/私有)方法量化完全相同。

多个线程表明高级convert函数仅用于将网页调色板暴露在网页调色板中。或"映射到最近的N种颜色"。这似乎在1.1.6及更高版本略有改变,但文档和实现仍然不完整。在http://comments.gmane.org/gmane.comp.python.image/2947,其中一个开发者建议阅读PIL / Image.py源。

所以,看起来你需要做的事情。无论Image.convertImage.WEB模式中做什么,您都希望这样做 - 但是使用由Image.quantize(colors)生成的调色板,而不是网页调色板。

当然,大多数内容都发生在C代码中(self.im.quantizeself.im.convert等),但你可以做类似伪代码的事情:

dummy = img.convert(mode='P', paletter='ADAPTIVE', colors=16)
intermediate = img.copy()
intermediate.setpalette(dummy.palette)
dithered = intermediate._new(intermediate.im.convert('P', Image.FLOYDSTEINBERG))

然后,你可能不会。您可能需要查看C标头甚至来源以查找。或者也许在PIL邮件列表上询问。

PS,如果您不熟悉PIL的内容,img.im是PIL图像对象img下面的C成像对象。从我过去的经验来看,前3次浏览PIL代码并不清楚,然后突然间一切都变得更有意义。

相关问题