如何打开优化的 GIF 没有错误?

How to open optimized GIF without bugs?

所以这个 GIF 在打开之前看起来非常完美:

但是,当使用 Pillow 打开时使用

imageObject = Image.open(path.join(petGifs, f"{pokemonName}.gif"))

它出错了,添加了与源图像颜色相似的各种框。这是一个示例帧,但几乎每一帧都是不同的,并且它在不同的位置取决于 GIF:

唯一解决这个问题的方法是 ezgif 的取消优化选项(在他们的 optimize page 中找到)。但是,我需要在每个 GIF 上都这样做,而且有很多。

我需要一种批量取消优化的方法,或者一种在 Python(目前使用 Pillow)中打开 GIF 的新方法,这将解决这个问题。

您可以尝试使用:

from PIL import Image, ImageSequence

im = Image.open(f"{pokemonName}.gif")

index = 1
for frame in ImageSequence.Iterator(im):
    frame.save("frame%d.png" % index)
    index += 1

至少对于提取正确的单帧可能有一个解决方案。

所有帧(第一帧除外)的disposal方法设置为2,即“恢复为背景颜色”。

深入了解 Pillow 的源代码,您会找到相应的 line where the disposal method 2 is considered,并且在下文中,您会发现:

# by convention, attempt to use transparency first
color = (
    frame_transparency
    if frame_transparency is not None
    else self.info.get("background", 0)
)
self.dispose = Image.core.fill("P", dispose_size, color)

如果您检查错误的框架,您会注意到不需要的框的这种深绿色位于调色板的位置 0。因此,似乎选择了错误的颜色进行处理,因为 – 我还不知道为什么 – 选择了上面的 else 案例而不是使用透明度信息 – 本来就在那里!

所以,让我们重写可能有问题的东西:

from PIL import Image, ImageSequence

# Open GIF
gif = Image.open('223vK.gif')

# Initialize list of extracted frames
frames = []

for frame in ImageSequence.Iterator(gif):

    # If dispose is set, and color is set to 0, use transparency information
    if frame.dispose is not None and frame.dispose[0] == 0:
        frame.dispose = Image.core.fill('P', frame.dispose.size,
                                        frame.info['transparency'])

    # Convert frame to RGBA
    frames.append(frame.convert('RGBA'))

# Visualization overhead
import matplotlib.pyplot as plt
plt.figure(figsize=(8, 8))
for i, f in enumerate(frames, start=1):
    plt.subplot(8, 8, i), plt.imshow(f), plt.axis('off')
plt.tight_layout(), plt.show()

提取的帧如下所示:

我觉得不错。

如果偶然将透明度信息实际设置为 0,则此处不应造成任何伤害,因为我们(重新)设置了仍然正确的透明度信息。

我不知道,(重新)保存到 GIF 是否可行,因为帧现在处于 RGBA 模式,从那里保存到 GIF 也很棘手。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.3
Matplotlib:    3.4.2
Pillow:        8.3.1
----------------------------------------

我找到了一个我喜欢的未优化 gif 的解决方案,可能对您有用。

它使用 gifsicle 库,这是一个用于处理 gif 的命令行工具。至关重要的是,gifsicle 可以让你像你一样取消优化 gif(我认为你的 gif 中优化的具体名称是“累积层”)。

使用您选择的包管理器安装它后,您可以通过 Python 的 subprocess 库在您的代码中调用它,或者您自己从命令行使用它。

您特别提到了一种批量取消优化的方法,您可以使用 gifsicle 通过类似的方式非常轻松地做到这一点:

gifsicle -U -b *.gif

这将同时用未优化的版本覆盖工作目录中的每个 gif。如果您想保留优化的副本,请进行备份。有关如何使用 gifsicle 的更多信息,请参阅 manual page

gif未优化后python应该可以正常打开