【问题标题】:Are RGBA PNGs unsupported in Python 3.5 + Pillow?Python 3.5 + Pillow 是否不支持 RGBA PNG?
【发布时间】:2017-05-25 09:40:57
【问题描述】:

* 编辑 * 不,我不是要转换 .BMP 只需简单地加载 PNG 并在 tk Canvas 中渲染它(透明位实际上是透明的。)

目标: 什么以透明方式加载 PNG 文件并使用 Python3 在 tkinter Canvas 中渲染它们(并使用 Pillow 支持 PIL)

问题: 当加载为 RGBA 时,它们无法在画布中呈现。将它们转换为 RGB,它们将呈现,但当然没有透明度。

环境: Mac OSX, Python 3.5 安装并验证 Pillow 在 3.5 路径中

注意事项: CuriosityRover.png 确实是一个 RGBA,打印声明证实,并通过 finder 显示灰色背景和 Photoshop 以透明度保存网页进行验证。

我试过像这样只提取 alpha 层:

 alpha = img.convert('RGBA').split()[-1]

调用 alpha.show() 确实在预览 alpha 层中显示我,但它无法在画布小部件中呈现。

我还尝试使用 ImageOps.invert(alpha) 反转 alpha 层 (在应用反转后通过调用 .show() 进行验证,我在预览中看到了反向 alpha 层。)

我尝试过创建这样的矩形透明区域: 透明区域 = (0, 0, 300, 300) mask = Image.new('L', curosity.size, color=255) 绘制 = ImageDraw.Draw(蒙版) draw.rectangle(transparent_area, fill=0) img.putalpha(掩码)

确实可以创建一个透明的矩形区域,所以看起来 canvas.create_image 可以很好地处理透明度,但是不知何故,我无法创建透明度数据正确的 PhotoImage。

一天中我打开了很多堆栈溢出选项卡,我很尴尬,我无法弄清楚这一点。

这似乎是世界上最简单的事情。我做错了什么?

import tkinter as tk
from PIL import Image, ImageTk

img = Image.open("./Assets/CuriosityRover.png")
img2 = Image.open("./Assets/CuriosityRover.png").convert('RGB')

img.show()  # Shows the image just fine in preview
print(img.format, img.size, img.mode)

root = tk.Tk()
photo = ImageTk.PhotoImage(img)  # img fails render, img2 works but no alpha

canvas = tk.Canvas(root, width=600, height=600, bg="black")

canvas.create_image((300, 300), image=photo)
canvas.grid(row=0, column=0)

root.mainloop()

【问题讨论】:

  • Load RGBA bitmap with PIL的可能重复
  • 不,我没有加载 .BMP,我正在加载 PNG
  • “渲染失败”是什么意思?你收到错误信息还是什么?我只能说它适用于 Linux,所以问题只能在 Mac 上。顺便说一句:你只尝试过一张图片吗?
  • 感谢您在 Linux 上试用。对不起,我应该更清楚,它渲染,但它把透明部分绘制为不透明的白色。我尝试了两个不同的图像。
  • RGB 模式会渲染但不透明位,RGBA 模式不会渲染,但 RGBA 会 .show()

标签: python python-3.x tkinter png alpha


【解决方案1】:

哇!我解决了这个问题。

TL;DR - 是的 RGBA* PNGS 在 Pillow/Tkinker 中不支持 - 但是下面有一个变通方法,强制 Alpha 通道的值只有 0 或 255

*通道不能有除 0 或 255 以外的任何值,如果有,则不会绘制整个图像(即使是 Alpha 通道中具有 255 的像素。)

加长版: 它让我大吃一惊。原来我的问题是 Photoshop 用 8 位信息保存了 Alpha 通道,因此我的测试图像在我肉眼看不到的范围内具有微妙的透明度。当我查看这些图像时,它们看起来要么不透明,要么透明。

但是通过比较矩形透明度测试用例成功后的实际字节,我可以看到 Image 只需要 0 表示透明或 255 表示不透明(由于 Tkinter 动态布局 GUI,它不知道是什么颜色是下面像素的颜色,在部分透明的情况下混合。)

所以,为了解决这个问题,我现在通过我在下面创建的这个辅助函数运行我的图像,它翻转 alpha 通道上的 8 位信息并强制它们为 0 或 255。我有点武断地选择了50及以下的情况我会认为它是透明的。

希望其他人在不得不从头开始解决这个问题之前看到这一点。

# Fixes the issue when trying to render RBGAs that have 8bits of information in the alpha channel
# Turns your image into 8 bits on RGB and then 1 bit on the A channel
# This will render correctly
# See the example below for how to use

from PIL import Image


def flattenAlpha(img):
    alpha = img.split()[-1]  # Pull off the alpha layer
    ab = alpha.tobytes()  # Original 8-bit alpha

    checked = []  # Create a new array to store the cleaned up alpha layer bytes

    # Walk through all pixels and set them either to 0 for transparent or 255 for opaque fancy pants
    transparent = 50  # change to suit your tolerance for what is and is not transparent

    p = 0
    for pixel in range(0, len(ab)):
        if ab[pixel] < transparent:
            checked.append(0)  # Transparent
        else:
            checked.append(255)  # Opaque
        p += 1

    mask = Image.frombytes('L', img.size, bytes(checked))

    img.putalpha(mask)

    return img

# Run this as a test case.
# Assumes that you have a PNG named "CuriosityRover.png"
# that is an RGBA with varying levels of Alpha in the
# subdirectory assets from your working directory

if __name__ == "__main__":
    from PIL import ImageTk
    import tkinter as tk

    img = Image.open("./Assets/CuriosityRover.png")

    img = flattenAlpha(img)
    root = tk.Tk()

    photo = ImageTk.PhotoImage(img)
    canvas = tk.Canvas(root, width=600, height=600, bg="red")

    canvas.create_image((300, 300), image=photo)
    canvas.grid(row=0, column=0)

    root.mainloop()

【讨论】:

  • 我认为你的结论可能不正确,但我得稍后验证。
  • 我很乐意犯错。大量的测试似乎支持这个假设......
  • 您的辅助函数运行良好。 GIMP 创建的透明 png 没有通过辅助函数修复显示和运行它们,我遇到了完全相同的问题。
猜你喜欢
  • 2018-02-09
  • 1970-01-01
  • 2017-08-20
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多