我正在寻找一种获得gif帧数的方法。我正在寻找谷歌,stackoverflow和任何外部网站,我只发现垃圾!有人知道怎么做吗?我只需要简单数量的gif帧。
答案 0 :(得分:15)
只需解析文件,gif非常简单:
class GIFError(Exception): pass
def get_gif_num_frames(filename):
frames = 0
with open(filename, 'rb') as f:
if f.read(6) not in ('GIF87a', 'GIF89a'):
raise GIFError('not a valid GIF file')
f.seek(4, 1)
def skip_color_table(flags):
if flags & 0x80: f.seek(3 << ((flags & 7) + 1), 1)
flags = ord(f.read(1))
f.seek(2, 1)
skip_color_table(flags)
while True:
block = f.read(1)
if block == ';': break
if block == '!': f.seek(1, 1)
elif block == ',':
frames += 1
f.seek(8, 1)
skip_color_table(ord(f.read(1)))
f.seek(1, 1)
else: raise GIFError('unknown block type')
while True:
l = ord(f.read(1))
if not l: break
f.seek(l, 1)
return frames
答案 1 :(得分:12)
您使用哪种方法来加载/操作框架?你在用PIL吗?如果没有,我建议您查看:Python Imaging Library,特别是the PIL gif page。
现在,假设您使用PIL读取gif,确定您正在查看哪个帧是一件非常简单的事情。 seek 将转到特定的框架, tell 将返回您正在查看的框架。
from PIL import Image
im = Image.open("animation.gif")
# To iterate through the entire gif
try:
while 1:
im.seek(im.tell()+1)
# do something to im
except EOFError:
pass # end of sequence
否则,我相信你只能在寻找异常(EOFError)之前找到gif中的帧数。
答案 2 :(得分:4)
我最近遇到了同样的问题,发现特别缺乏有关GIF的文档。这是我使用imageio's get_reader读取图像字节的解决方案(例如,如果您仅使用fetched the image via HTTP,则可以方便地将帧存储在numpy matrices中):
import imageio
gif = imageio.get_reader(image_bytes, '.gif')
# Here's the number you're looking for
number_of_frames = len(gif)
for frame in gif:
# each frame is a numpy matrix
如果只需要打开文件,请使用:
gif = imageio.get_reader('cat.gif')
答案 3 :(得分:1)
好吧,9 年时间可能有点长,但这是我的答案
Dim fr() As DataRow
Dim Itmnmbr As string = "i-2051"
fr = dt.Select("item = 'i-2051'")
答案 4 :(得分:0)
如果您使用的是PIL(Python Imaging Library),则可以使用图像对象的n_frames属性。
答案 5 :(得分:0)
这里有一些代码可以为您提供一个包含 GIF 中每一帧的持续时间值的列表:
from PIL import Image
gif_image = Image.open("animation.gif")
metadata = []
for i in range(gif_image.n_frames):
gif_image.seek(i)
duration = gif_image.info.get("duration", 0)
metadata.append(duration)
您可以修改上面的代码以从每个帧中捕获其他数据,例如背景颜色索引、透明度或版本。每个帧上的 info
字典如下所示:
{'version': b'GIF89a', 'background': 0, 'transparency': 100, 'duration': 70}
答案 6 :(得分:-1)
为@adw's answer构建的更详尽的解决方案,适用于不想依赖第三方模块(如Pillow / PIL)的人,可在Python 2和3中使用。
import sys
is_py2 = sys.version_info[0] == 2
def gif_frames(image_path):
"""Return frames in an animated gif
primarily used this great deep dive into the structure of an animated gif
to figure out how to parse it:
http://www.matthewflickinger.com/lab/whatsinagif/bits_and_bytes.asp
:param image_path: string, assumed to be a path to a gif file
:returns: integer, how many frames the gif contains
"""
image_count = 0
def skip_color_table(fp, packed_byte):
"""this will fp.seek() completely passed the color table"""
if is_py2:
packed_byte = int(packed_byte.encode("hex"), 16)
has_gct = (packed_byte & 0b10000000) >> 7
gct_size = packed_byte & 0b00000111
if has_gct:
global_color_table = fp.read(3 * pow(2, gct_size + 1))
def skip_image_data(fp):
"""skips the image data, which is basically just a series of sub blocks
with the addition of the lzw minimum code to decompress the file data"""
lzw_minimum_code_size = fp.read(1)
skip_sub_blocks(fp)
def skip_sub_blocks(fp):
"""skips over the sub blocks
the first byte of the sub block tells you how big that sub block is, then
you read those, then read the next byte, which will tell you how big
the next sub block is, you keep doing this until you get a sub block
size of zero"""
num_sub_blocks = ord(fp.read(1))
while num_sub_blocks != 0x00:
fp.read(num_sub_blocks)
num_sub_blocks = ord(fp.read(1))
with open(image_path, "rb") as fp:
header = fp.read(6)
if header == b"GIF89a": # GIF87a doesn't support animation
logical_screen_descriptor = fp.read(7)
skip_color_table(fp, logical_screen_descriptor[4])
b = ord(fp.read(1))
while b != 0x3B: # 3B is always the last byte in the gif
if b == 0x21: # 21 is the extension block byte
b = ord(fp.read(1))
if b == 0xF9: # graphic control extension
block_size = ord(fp.read(1))
fp.read(block_size)
b = ord(fp.read(1))
if b != 0x00:
raise ValueError("GCT should end with 0x00")
elif b == 0xFF: # application extension
block_size = ord(fp.read(1))
fp.read(block_size)
skip_sub_blocks(fp)
elif b == 0x01: # plain text extension
block_size = ord(fp.read(1))
fp.read(block_size)
skip_sub_blocks(fp)
elif b == 0xFE: # comment extension
skip_sub_blocks(fp)
elif b == 0x2C: # Image descriptor
# if we've seen more than one image it's animated
image_count += 1
# total size is 10 bytes, we already have the first byte so
# let's grab the other 9 bytes
image_descriptor = fp.read(9)
skip_color_table(fp, image_descriptor[-1])
skip_image_data(fp)
b = ord(fp.read(1))
return image_count