如何加载动画 GIF 并获取 Pygame 中的所有单个帧?
How can I load an animated GIF and get all of the individual frames in Pygame?
首先,如果这是重复的,我们深表歉意。我找到的答案似乎无关紧要,但也许我正在使用错误的关键字进行搜索。我想做的是获取动画 GIF 并将其拆分为帧列表。基本上是这样的:
frames = []
for frame in split_animated_gif("some_animated_gif.gif"):
frames.append(frame)
其中 split_animated_gif returns 表面列表,每个表面都是 GIF 的一个框架,按顺序排列。谢谢你的帮助。
编辑:经过更多的窥探,我发现一段代码成功地为我显示了 pygame 中的动画 GIF。它可以在 https://github.com/piantado/kelpy/blob/master/kelpy/GIFImage.py 找到。不过,非常感谢您的帮助。
Pygame本身不支持gif动画,文档中有说明。所以你必须
1) 在加载 sprite 或图像时使用其他一些代码/库来拆分 gif。那些你可以通过谷歌搜索 "python split gif" 之类的东西找到的。例如。 Python: Converting GIF frames to PNG
2) 如果您自己创建了 gif,只需逐帧再次导出精灵
无论哪种方式,您都必须手动完成动画部分。您可以通过谷歌搜索 "pygame animation" 找到大量教程。例如。 Animated sprite from few images
此代码使用 PIL / pillow 库。
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 主页上介绍了 GIFImage 库:
This library adds GIF animation playback to pygame.
另一种选择是使用库将 GIF 逐帧加载到列表中。
例如使用 Pillow library (pip install Pillow).
编写一个函数,可以将 PIL 图像转换为 pygame.Surface
并使用 PIL 库逐帧加载 GIF:
(另见 Extracting The Frames Of An Animated GIF Using Pillow and PIL and pygame.image)
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
或使用OpenCV/opencv-python library and VideoCapture
编写一个函数,可以将 cv2 pygame.image
图像转换为 pygame.Surface
并使用该库逐帧加载 GIF:
(另见 Read GIF files in Python and )
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
另见 Load animated 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()
首先,如果这是重复的,我们深表歉意。我找到的答案似乎无关紧要,但也许我正在使用错误的关键字进行搜索。我想做的是获取动画 GIF 并将其拆分为帧列表。基本上是这样的:
frames = []
for frame in split_animated_gif("some_animated_gif.gif"):
frames.append(frame)
其中 split_animated_gif returns 表面列表,每个表面都是 GIF 的一个框架,按顺序排列。谢谢你的帮助。
编辑:经过更多的窥探,我发现一段代码成功地为我显示了 pygame 中的动画 GIF。它可以在 https://github.com/piantado/kelpy/blob/master/kelpy/GIFImage.py 找到。不过,非常感谢您的帮助。
Pygame本身不支持gif动画,文档中有说明。所以你必须
1) 在加载 sprite 或图像时使用其他一些代码/库来拆分 gif。那些你可以通过谷歌搜索 "python split gif" 之类的东西找到的。例如。 Python: Converting GIF frames to PNG
2) 如果您自己创建了 gif,只需逐帧再次导出精灵
无论哪种方式,您都必须手动完成动画部分。您可以通过谷歌搜索 "pygame animation" 找到大量教程。例如。 Animated sprite from few images
此代码使用 PIL / pillow 库。
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 主页上介绍了 GIFImage 库:
This library adds GIF animation playback to pygame.
另一种选择是使用库将 GIF 逐帧加载到列表中。
例如使用 Pillow library (pip install Pillow).
编写一个函数,可以将 PIL 图像转换为 pygame.Surface
并使用 PIL 库逐帧加载 GIF:
(另见 Extracting The Frames Of An Animated GIF Using Pillow and PIL and pygame.image)
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
或使用OpenCV/opencv-python library and VideoCapture
编写一个函数,可以将 cv2 pygame.image
图像转换为 pygame.Surface
并使用该库逐帧加载 GIF:
(另见 Read GIF files in Python and
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
另见 Load animated 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()