如何在没有bug的情况下打开优化的GIF?

2024-09-30 16:30:38 发布

您现在位置:Python中文网/ 问答频道 /正文

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

The gif before python opens

但是,当使用枕头打开使用

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

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

one of the frames after the gif is opened in Python

another frame after the gif is opened in Python

唯一能解决这个问题的是ezgif的unoptimize选项(在它们的optimize page中找到)。但是,我需要在每个GIF上都这样做,而且有很多

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


Tags: path方法图像image示例颜色opengif
2条回答

至少对于提取适当的单帧,可能有一个解决方案

所有帧(第一帧除外)的^{}方法设置为2,即“恢复到背景色”

浏览Pillow的源代码,您将找到相应的line where the disposal method ^{} 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()

提取的帧如下所示:

Output

这对我来说很好

如果碰巧,透明度信息实际上设置为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

相关问题 更多 >