繁体   English   中英

python 3.5 +枕头不支持RGBA PNG吗?

[英]Are RGBA PNGs unsupported in Python 3.5 + Pillow?

*编辑*不,我不尝试转换.BMP,只需加载PNG并将其呈现在tk画布中(透明位实际上是透明的)。

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

问题 :作为RGBA加载时,它们无法在画布中渲染。 将它们转换为RGB并可以渲染,但是当然没有透明度。

环境 :Mac OSX,Python 3.5已安装并经过验证,Pillow位于3.5路径中

注意 :CuriosityRover.png的确是RGBA,打印声明确认并用finder显示灰色背景和Photoshop透明保存web进行了验证。

我试图像这样仅提取出alpha层:

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

确实调用alpha.show()确实可以在Preview alpha层中显示我,但是无法在canvas小部件中呈现。

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

我试图创建像这样的矩形透明区域:transparent_area =(0,0,300,300)mask = Image.new('L',curosity.size,color = 255)draw = ImageDraw.Draw(mask)draw.rectangle (透明区域,填充= 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()

活泉! 我解决了

TL; DR-枕头/手推车不支持 RGBA * PNGS是-但以下方法无法解决,并迫使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()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM