至少对于提取正确的单帧可能有解决方案。
所有帧(第一帧除外)的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
----------------------------------------