简体   繁体   English

如何加载动画 GIF 并获取 Pygame 中的所有单个帧?

[英]How can I load an animated GIF and get all of the individual frames in Pygame?

First of all, sorry if this is a duplicate.首先,对不起,如果这是重复的。 The answers that I found either seemed irrelevant but perhaps I'm searching with the wrong keywords.我找到的答案似乎无关紧要,但也许我正在使用错误的关键字进行搜索。 What I'd like to do is to take an animated GIF and split it up into a list of frames.我想做的是获取动画 GIF 并将其拆分为帧列表。 Basically, something like this:基本上,是这样的:

frames = []
for frame in split_animated_gif("some_animated_gif.gif"):
    frames.append(frame)

where split_animated_gif returns a list of surfaces, each of which is a frame of the GIF, in order.其中 split_animated_gif 返回一个按顺序排列的表面列表,每个表面都是 GIF 的一个帧。 Thank you for your help.感谢您的帮助。

EDIT: After some more snooping, I found a piece of code that successfully displayed an animated GIF in pygame for me.编辑:经过更多的窥探,我找到了一段代码,它成功地为我在 pygame 中显示了动画 GIF。 It can be found athttps://github.com/piantado/kelpy/blob/master/kelpy/GIFImage.py .它可以在https://github.com/piantado/kelpy/blob/master/kelpy/GIFImage.py找到。 Your help was much appreciated, though.不过,非常感谢您的帮助。

Pygame itself does not support animated gifs, which is stated in the documentation. Pygame 本身不支持 gif 动画,这在文档中有所说明。 So you'll have to所以你必须

1) use some other piece of code / library to split the gif when you're loading your sprites or images. 1) 在加载精灵或图像时,使用其他一些代码/库来分割 gif。 Those you would find just by googling for "python split gif" or something.那些你可以通过谷歌搜索“python split gif”或其他东西找到的。 Eg Python: Converting GIF frames to PNG例如Python:将 GIF 帧转换为 PNG

2) if you created the gif yourself, just export your sprites again frame by frame 2) 如果您自己创建了 gif,只需逐帧再次导出您的精灵

Either way, you'll have to do the animating part by hand.无论哪种方式,您都必须手动完成动画部分。 Which for you'll find plenty of tutorials by googling "pygame animation".您可以通过谷歌搜索“pygame 动画”找到大量教程。 Eg Animated sprite from few images例如来自少数图像的动画精灵

This code does it using PIL / pillow library.这段代码使用 PIL/枕头库来完成。

from PIL import Image

def split_animated_gif(gif_file_path):
    ret = []
    gif = Image.open(gif_file_path)
    for frame_index in range(gif.n_frames):
        gif.seek(frame_index)
        frame_rgba = gif.convert("RGBA")
        pygame_image = pygame.image.fromstring(
            frame_rgba.tobytes(), frame_rgba.size, frame_rgba.mode
        )
        ret.append(pygame_image)
    return ret

PyGame respectively the pygame.image module can only handle non-animated GIFs . PyGame分别是pygame.image模块只能处理非动画GIF
But on the PyGame homepage is introduced the GIFImage library:但是在PyGame主页上引入了GIFImage库:

This library adds GIF animation playback to pygame.这个库为 pygame 添加了 GIF 动画播放。


Another option is to use a library to load the GIF frame by frame to a list.另一种选择是使用库将 GIF 逐帧加载到列表中。

For instance use the Pillow library ( pip install Pillow ).例如使用Pillow库( pip install Pillow )。

Write a function, that can convert a PIL image to a pygame.Surface and use the PIL library to load a GIF frame by frame:编写一个函数,可以将 PIL 图像转换为pygame.Surface并使用 PIL 库逐帧加载 GIF:
(see also Extracting The Frames Of An Animated GIF Using Pillow and PIL and pygame.image ) (另请参阅使用 PillowPIL 以及 pygame.image 提取动画 GIF 的帧

from PIL import Image, ImageSequence
def pilImageToSurface(pilImage):
    mode, size, data = pilImage.mode, pilImage.size, pilImage.tobytes()
    return pygame.image.fromstring(data, size, mode).convert_alpha()

def loadGIF(filename):
    pilImage = Image.open(filename)
    frames = []
    if pilImage.format == 'GIF' and pilImage.is_animated:
        for frame in ImageSequence.Iterator(pilImage):
            pygameImage = pilImageToSurface(frame.convert('RGBA'))
            frames.append(pygameImage)
    else:
        frames.append(pilImageToSurface(pilImage))
    return frames

Or use OpenCV / opencv-python library and VideoCapture或者使用OpenCV / opencv-python库和VideoCapture

Write a function, that can convert a cv2 pygame.image image to a pygame.Surface a nd use the library to load a GIF frame by frame:写的功能,能够在转换CV2 pygame.image图像向pygame.Surface一个第二使用该库由帧加载一个GIF帧:
(see also Read GIF files in Python and How do I convert an OpenCV (cv2) image (BGR and BGRA) to a pygame.Surface object ) (另请参阅在 Python 中读取 GIF 文件如何将 OpenCV (cv2) 图像(BGR 和 BGRA)转换为 pygame.Surface 对象

import cv2
def cv2ImageToSurface(cv2Image):
    size = cv2Image.shape[1::-1]
    format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
    cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
    surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
    return surface.convert_alpha() if format == 'RGBA' else surface.convert()

def loadGIF(filename):
    gif = cv2.VideoCapture(filename)
    frames = []
    while True:
        ret, cv2Image = gif.read()
        if not ret:
            break
        pygameImage = cv2ImageToSurface(cv2Image)
        frames.append(pygameImage)
    return frames

See also Load animated GIF and a simple animated gif viewer example:另请参阅加载动画 GIF和一个简单的动画 gif 查看器示例:

import pygame
import cv2

def cv2ImageToSurface(cv2Image):
    size = cv2Image.shape[1::-1]
    format = 'RGBA' if cv2Image.shape[2] == 4 else 'RGB'
    cv2Image[:, :, [0, 2]] = cv2Image[:, :, [2, 0]]
    surface = pygame.image.frombuffer(cv2Image.flatten(), size, format)
    return surface.convert_alpha() if format == 'RGBA' else surface.convert()

def loadGIF(filename):
    gif = cv2.VideoCapture(filename)
    frames = []
    while True:
        ret, cv2Image = gif.read()
        if not ret:
            break
        pygameImage = cv2ImageToSurface(cv2Image)
        frames.append(pygameImage)
    return frames

pygame.init()
window = pygame.display.set_mode((500, 500))
clock = pygame.time.Clock()

gifFrameList = loadGIF(r"rubber_ball.gif")
currentFrame = 0

run = True
while run:
    clock.tick(20)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    window.fill(0)

    rect = gifFrameList[currentFrame].get_rect(center = (250, 250))
    window.blit(gifFrameList[currentFrame], rect)
    currentFrame = (currentFrame + 1) % len(gifFrameList)

    pygame.display.flip()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM