Python, how i can get gif frames

不羁岁月 提交于 2019-11-27 06:21:31

问题


I am looking some kind method to get gif frames number. i am looking on google, stackoverflow and any outher sites and i find only rubbish!! Someone know how to do it? i need only simple number of gif frames.


回答1:


Just parse the file, gifs are pretty simple:

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



回答2:


Which method are you using to load/manipulate the frame? Are you using PIL? If not, I suggest checking it out: Python Imaging Library and specifically the PIL gif page.

Now, assuming you are using PIL to read in the gif, it's a pretty simple matter to determine which frame you are looking at. seek will go to a specific frame and tell will return which frame you are looking at.

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

Otherwise, I believe you can only find the number of frames in the gif by seeking until an exception (EOFError) is raised.




回答3:


A more exhaustive solution that builds on @adw's answer for anyone who doesn't want to rely on a third party module like Pillow/PIL, works in both Python 2 and 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


来源:https://stackoverflow.com/questions/7503567/python-how-i-can-get-gif-frames

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!