问题描述
所以这个 GIF 在打开前看起来非常好:
但是,当使用 Pillow 打开时使用
imageObject = Image.open(path.join(petGifs,f"{pokemonName}.gif"))
它出错了,添加了与源图像颜色相似的各种框。这是一个示例帧,但几乎每一帧都不同,并且根据 GIF 在不同的位置:
唯一能解决这个问题的是ezgif的unoptimize选项(在他们的optimize page中找到)。但是,我需要在每个 GIF 上都这样做,而且有很多。
我需要一种批量取消优化的方法,或者一种在 Python 中打开 GIF 的新方法(目前使用 Pillow),以解决这个问题。
解决方法
至少对于提取正确的单帧来说,可能有一个解决方案。
所有帧(除了第一个)的 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
----------------------------------------
,
您可以尝试使用:
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