在 Pillow 中使用调色板模式 GIF 保持透明度

Maintaining transparency with palette mode GIFs in Pillow

我正在尝试使用包含一个透明度索引的调色板拍摄 GIF,并使用 Pillow 创建裁剪子图像。但是,当使用 crop() 方法时,结果不再透明。

original = Image.open("filename.gif")
print(original.mode) # prints "P", as it should
transparent = original.info["transparency"]
print(transparent) # prints the correct index of the transparent color
cropped = original.crop((0, 0, 10, 10))
print(cropped.info) # transparency no longer present
cropped.info["transparency"] = 255
print(cropped.info) # key is entered, but not transparent in a drawn image

如何在Pillow中通过操作维护或恢复透明索引?如上所示,即使我 "brute-force" 将透明度索引添加回 "info" 字典,那显然不是 Python 寻找要指定的索引的地方。该文档还提到某些方法如 crop() 是惰性的并且不会传输所有图像信息,那么有没有办法将这些信息重新添加到 Image 对象中?文档建议我可以通过保存一个新的 GIF 文件来做到这一点,但是在程序完成后我不需要子图像 运行 并显示它们。

编辑以添加以下附加信息:

原图,GIMP制作(圆圈为红色,用IrfanView标记为透明色)

我的代码的输出,圆圈恢复为可见的红色

我的整个程序在这里:

from tkinter import *
from tkinter import ttk
from PIL import Image
from PIL import ImageTk

class Main:
    def __init__(self):
        self.root = Tk()
        self.background = Canvas(self.root)
        self.background.grid(column=0,row=0)
        self.Draw()

    def Draw(self):
        original = Image.open("Transparency_test.gif")
        print(original.mode) # prints "P", as it should
        transparent = original.info["transparency"]
        print(transparent) # prints the correct index of the transparent color
        cropped = original.crop((0, 0, 50, 50))
        print(cropped.info) # transparency no longer present

        test_uncropped = ImageTk.PhotoImage(image=original)
        test_cropped = ImageTk.PhotoImage(image=cropped)

        self.background.create_image((0,0), image=test_uncropped, anchor=NW)
        self.background.create_image((100,0), image=test_cropped, anchor=NW)

        self.root.mainloop()

instance = Main()

我不确定这是最有效的解决方案,但我通过制作一个调整大小的图像副本,然后将原始图像的像素粘贴到它上面来实现它。我想结果是你所期望的。

    cropped = original.crop((0, 0, 50, 50))
    cropped.load()
    print(cropped.info) # transparency no longer present

    copied = original.resize((50,50))
    copied.paste(original, (0, 0))
    print(copied.info) # transparency present

    test_uncropped = ImageTk.PhotoImage(image=original)
    test_cropped = ImageTk.PhotoImage(image=cropped)
    test_copied = ImageTk.PhotoImage(image=copied)

    self.background.create_image((0,0), image=test_uncropped, anchor=NW)
    self.background.create_image((100,0), image=test_cropped, anchor=NW)
    self.background.create_image((200,0), image=test_copied, anchor=NW)