zoukankan      html  css  js  c++  java
  • Python 提取GIF里面的所有帧

    安装依赖

    pip install --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple Pillow

    放几个gif

    PRED-121.gif

    代码

    version: 1.0

    ## version: 1.0
    
    import os
    import sys
    from PIL import Image
    
    def extractFrames(inGif, outFolder):
        frame = Image.open(inGif)
        nframes = 0
        while frame:
            frame.save('%s/%s-%s.png' % (outFolder, os.path.basename(inGif), nframes))
            nframes += 1
            try:
                frame.seek(nframes)
            except EOFError:
                break;
        return True
    
    if __name__ == '__main__':
        image = os.path.abspath(sys.argv[1])
        dest = os.path.join(os.path.dirname(image), "dest")
        if not os.path.exists(dest):
            os.mkdir(dest)
        extractFrames(image, dest)
    

    version: 2.0

    ## version: 2.0
    
    import sys
    import os
    from PIL import Image
    
    '''
    I searched high and low for solutions to the "extract animated GIF frames in Python"
    problem, and after much trial and error came up with the following solution based
    on several partial examples around the web (mostly Stack Overflow).
    
    There are two pitfalls that aren't often mentioned when dealing with animated GIFs -
    firstly that some files feature per-frame local palettes while some have one global
    palette for all frames, and secondly that some GIFs replace the entire image with
    each new frame ('full' mode in the code below), and some only update a specific
    region ('partial').
    
    This code deals with both those cases by examining the palette and redraw
    instructions of each frame. In the latter case this requires a preliminary (usually
    partial) iteration of the frames before processing, since the redraw mode needs to
    be consistently applied across all frames. I found a couple of examples of
    partial-mode GIFs containing the occasional full-frame redraw, which would result
    in bad renders of those frames if the mode assessment was only done on a
    single-frame basis.
    
    Nov 2012
    '''
    
    
    def analyseImage(path):
        '''
        Pre-process pass over the image to determine the mode (full or additive).
        Necessary as assessing single frames isn't reliable. Need to know the mode
        before processing all frames.
        '''
        im = Image.open(path)
        results = {
            'size': im.size,
            'mode': 'full',
        }
        try:
            while True:
                if im.tile:
                    tile = im.tile[0]
                    update_region = tile[1]
                    update_region_dimensions = update_region[2:]
                    if update_region_dimensions != im.size:
                        results['mode'] = 'partial'
                        break
                im.seek(im.tell() + 1)
        except EOFError:
            pass
        return results
    
    
    def processImage(path,dest):
        '''
        Iterate the GIF, extracting each frame.
        '''
        mode = analyseImage(path)['mode']
    
        im = Image.open(path)
    
        i = 0
        p = im.getpalette()
        last_frame = im.convert('RGBA')
    
        try:
            while True:
                print("saving %s (%s) frame %d, %s %s" % (path, mode, i, im.size, im.tile))
    
                '''
                If the GIF uses local colour tables, each frame will have its own palette.
                If not, we need to apply the global palette to the new frame.
                '''
                if not im.getpalette():
                    im.putpalette(p)
    
                new_frame = Image.new('RGBA', im.size)
    
                '''
                Is this file a "partial"-mode GIF where frames update a region of a different size to the entire image?
                If so, we need to construct the new frame by pasting it on top of the preceding frames.
                '''
                if mode == 'partial':
                    new_frame.paste(last_frame)
    
                new_frame.paste(im, (0, 0), im.convert('RGBA'))
                new_frame.save(os.path.join(dest, '%s-%d.png' % (''.join(os.path.basename(path).split('.')[:-1]), i)), 'PNG')
    
                i += 1
                last_frame = new_frame
                im.seek(im.tell() + 1)
        except EOFError:
            pass
    
    if __name__ == "__main__":
        image = os.path.abspath(sys.argv[1])
        dest = os.path.join(os.path.dirname(image), "dest")
        if not os.path.exists(dest):
            os.mkdir(dest)
        processImage(image, dest)
    
  • 相关阅读:
    理解 QEMU/KVM 和 Ceph(2):QEMU 的 RBD 块驱动(block driver)
    Neutron VxLAN + Linux Bridge 环境中的网络 MTU
    理解 QEMU/KVM 和 Ceph(1):QEMU-KVM 和 Ceph RBD 的 缓存机制总结
    [译] 企业级 OpenStack 的六大需求(第 3 部分):弹性架构、全球交付
    [译] 企业级 OpenStack 的六大需求(第 2 部分):开放架构和混合云兼容
    [译] 企业级 OpenStack 的六大需求(第 1 部分):API 高可用、管理和安全
    Javascript中的Array(数组) 、{}(映射) 与JSON解析
    HTML中显示特殊字符,如尖括号 “<”,">"等等
    Ubuntu 12.04 安装配置 Apache2
    Python中函数的参数传递与可变长参数
  • 原文地址:https://www.cnblogs.com/codworm/p/12444685.html
Copyright © 2011-2022 走看看