PIL透明背景中的残留白色像素

时间:2016-08-23 04:24:21

标签: python png python-imaging-library

我在另一个stackoverflow帖子中使用了以下代码

from PIL import Image as image

img = image.open('output.png')
img = img.convert("RGBA")
datas = img.getdata()

newData = []
for item in datas:
    if item[0] == 255 and item[1] == 255 and item[2] == 255:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)

img.putdata(newData)
img.save("img2.png", "PNG")

将我的png的背景转换为透明。但是,当我尝试在透明图像下方的powerpoint中添加一些形状时,它仍然留有一些残留的白色像素。有谁知道如何解决这个问题?

enter image description here

1 个答案:

答案 0 :(得分:2)

这些像素正好"白色"。您正在测试并从图像中删除的颜色为,其值为#FFFFFF。但是那些倾斜的线条是严重抗锯齿的,并且#34;褪色"从纯白色的背景到线条中心的纯色。

当放大一点时可以看到这一点:

antialiasing at work

您可以降低何时使像素完全透明的阈值:

if item[0] > 240 and item[1] > 240 and item[2] > 240:
    newData.append((255, 255, 255, 0))
else:
    newData.append(item)

但无论你做多少,你总会得到线条周围明显更亮的像素,或者 - 只匹配中心"线"颜色完全 - 断开像素,不再像原始线条那样。

但是没有理由对PNG图像使用是/否掩码! PNG支持完整的8位透明度,因此您可以制作“坚固”的内容。中心线完全不透明,纯白色完全透明,并且在这些值之间逐渐变暗的像素渐变。

如果您知道用于绘制线条的确切原始颜色,则效果最佳。使用Adobe PhotoShop进行测量,我得到类似#818695的内容。将这些值插入您的程序并调整“色调”。 (朝向白色)透明度,在完全可能的范围内展平,我建议使用此代码:

from PIL import Image as image

img = image.open('input.png')
img = img.convert("RGBA")
datas = img.getdata()

retain = (0x81,0x86,0x95)
retain_gray = (39*retain[0] + 50*retain[1] + 11*retain[2])

newData = []
for item in datas:
    if item[0] > retain[0] and item[1] > retain[1] and item[2] > retain[2]:
      # convert to grayscale
      val = 39*item[0] + 50*item[1] + 11*item[2]
      # invert
      val = 25500 - val;
      # difference with 'retain'
      val = retain_gray - val
      # scale down
      val = 255*val/retain_gray
      # invert to act as transparency
      transp = 255-val
      # apply transparency to original 'full' color value
      newData.append((retain[0], retain[1], retain[2], transp ))
    else:
      newData.append(item)

img.putdata(newData)
img.save("output.png", "PNG")
print "done"

它本质上是将输入图像转换为灰度,缩放它(因为从最暗到最轻的比例应该在0..255的完全透明度范围内),然后将其用作“透明&#” 39;字节。结果比开/关方法更好:

transparency added