Python 3.5 + Pillow 是否不支持 RGBA PNG?
Are RGBA PNGs unsupported in Python 3.5 + Pillow?
* 编辑 *
不,我不是要转换 .BMP
只需简单地加载 PNG 并将其呈现在 tk Canvas 中(透明位实际上是透明的。)
目标:
加载具有透明度的 PNG 文件并使用 Python3 在 tkinter Canvas 中渲染它们(并使用 Pillow 支持 PIL)
问题:
当加载为 RGBA 时,它们无法在 canvas 中呈现。将它们转换为 RGB,它们会渲染,但当然没有透明度。
环境:
Mac OSX, Python 3.5 安装并验证 Pillow 在 3.5 路径中
备注:
CuriosityRover.png 确实是一个 RGBA,打印语句确认,并使用显示灰色背景的 finder 和 Photoshop 保存透明网页进行验证。
我试过像这样只提取 alpha 层:
alpha = img.convert('RGBA').split()[-1]
调用 alpha.show() 确实在预览 alpha 层中显示了我,但它无法在 canvas 小部件中呈现。
我还尝试使用 ImageOps.invert(alpha) 反转 alpha 层
(通过在应用反转后调用 .show() 进行验证,我在预览中看到反向 alpha 层。)
我试过像这样创建矩形透明区域:
transparent_area = (0, 0, 300, 300)
掩码 = Image.new('L', curosity.size, 颜色=255)
绘制= ImageDraw.Draw(面具)
draw.rectangle(transparent_area, 填充=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 在 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()
* 编辑 * 不,我不是要转换 .BMP 只需简单地加载 PNG 并将其呈现在 tk Canvas 中(透明位实际上是透明的。)
目标: 加载具有透明度的 PNG 文件并使用 Python3 在 tkinter Canvas 中渲染它们(并使用 Pillow 支持 PIL)
问题: 当加载为 RGBA 时,它们无法在 canvas 中呈现。将它们转换为 RGB,它们会渲染,但当然没有透明度。
环境: Mac OSX, Python 3.5 安装并验证 Pillow 在 3.5 路径中
备注: CuriosityRover.png 确实是一个 RGBA,打印语句确认,并使用显示灰色背景的 finder 和 Photoshop 保存透明网页进行验证。
我试过像这样只提取 alpha 层:
alpha = img.convert('RGBA').split()[-1]
调用 alpha.show() 确实在预览 alpha 层中显示了我,但它无法在 canvas 小部件中呈现。
我还尝试使用 ImageOps.invert(alpha) 反转 alpha 层 (通过在应用反转后调用 .show() 进行验证,我在预览中看到反向 alpha 层。)
我试过像这样创建矩形透明区域: transparent_area = (0, 0, 300, 300) 掩码 = Image.new('L', curosity.size, 颜色=255) 绘制= ImageDraw.Draw(面具) draw.rectangle(transparent_area, 填充=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 在 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()