[英]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.