如何在Tkinter标签中使用PNG图像获得平滑的边缘

时间:2019-02-21 11:24:09

标签: python-3.x tkinter png

当我在tkinter画布上放置带有透明背景的png图像作为标签时,边缘会起波纹。如何获得光滑的边缘?请参阅两个示例:

enter image description here

enter image description here

我有以下代码:

import tkinter as tk # Python 3
master = tk.Tk()
master.minsize(500, 500)
master.geometry("500x500")
master.overrideredirect(True)
master.lift()
master.wm_attributes("-topmost", True)
master.wm_attributes("-transparentcolor", "white")
master.configure(background='white')

img = tk.PhotoImage(file="c:/temp/co.png")
panel = tk.Label(master, image = img, text="2", bg="white", compound=tk.CENTER, fg="#EFEFEF", font=("Helvetica", 14))
panel.place(x=300, y=200)

tk.mainloop()

这个想法是在Windows桌面的顶部放置一个透明层,在该透明层上放置包含png图像的小部件。

编辑: 以下是AivarasKazakevičius的回答:

enter image description here Enlarged

要播放的原始图像是: enter image description here

2 个答案:

答案 0 :(得分:0)

编辑#1

我已经确认问题是由于图像的预乘而引起的。最初,我认为绘制透明图像周围的白色边框是因为PIL如何加载图像。我试用了它,发现PIL可以很好地处理alpha和RGB值。

检查代码后,我发现我不喜欢的一件事:

panel = tk.Label(master, image=ph, text="2", bg="white", compound=tk.CENTER, fg="#EFEFEF", font=("Helvetica", 14))

bg="white"部分是我遇到的问题,因为我确定tcl / tk的源会干扰图像透明位的RGB值。现在,我无法获得tcl / tk源代码,因为我不知道如何访问它(对不起,仍然是编程的新手)。但是我的猜测是,所引用的代码行对图片的作用是这样的:它采用默认值或由用户bg设置的值ant将其溅到我们的透明图像上,从而使整个透明效果实际上无用。那我们该怎么办?好吧,我们必须为此过程准备图像-做预乘。编辑后的代码发布在下面。在下面,我发布了我所拥有的示例:

enter image description here

enter image description here

图像仍然看起来有点像素化。我相信,阅读有关预乘的更多信息并找到处理背景设置的tcl / tk源,将可以为预乘选择更好的参数。另外,您可以尝试将图像与白色背景手动合并,并尝试使用不同的方法进行预乘。

一些参考文献:

此问题的原因在这里得到了很好的描述(请查看注释以获取更多有用信息):https://nedbatchelder.com/blog/200801/truly_transparent_text_with_pil.html

这里也有关于预乘的很好的解释: http://www.spherevfx.com/written-training/miscellaneous-written-training/understanding-premultiplied-images/

希望这对您有帮助:

import tkinter as tk
from PIL import Image, ImageTk

master = tk.Tk()
master.geometry("500x500")
master.attributes("-topmost", True)
master.configure(background='white')
master.attributes("-transparentcolor", "white")

im = Image.open('A.tif')
width, height = im.size
px = im.load()
for i in range(width):
    for j in range(height):
        if px[i, j][3] != 0 and px[i, j][3] != 255:
            R = int(round(px[i, j][1] * px[i, j][3]))
            G = int(round(px[i, j][1] * px[i, j][3]))
            B = int(round(px[i, j][1] * px[i, j][3]))
            a = px[i, j][3]

            px[i, j] = (R, G, B, a)
            print(px[i, j])


ph = ImageTk.PhotoImage(im)
panel = tk.Label(master, image=ph, text="2", bg="white", compound=tk.CENTER,
                 fg="#EFEFEF", font=("Helvetica", 14))
panel.pack()
panel.image = ph  # image reference

tk.mainloop()

旁注:wm_attributes()与attribute()完全相同-我更喜欢使用后者以减少键入。

结果:

enter image description here

答案 1 :(得分:0)

问题是创建了新图像。结果图像中的“白色”颜色不再是纯白色,例如(255,255,223),而不是(255,255,255)。结果,透明蒙版无法覆盖这些像素,并且仍然可见。

如果背景色是固定的,则最简单的解决方案是创建一个没有白色透明色但已经具有相同背景色的图标。您也可以将其设置为透明颜色。 如果不是这种情况,则可以考虑使用中性的背景色而不是白色,并将其用作透明色。