'''
A fork of this gist https://gist.github.com/BigglesZX/4016539 .
Ported to Python3 and verify it with Pillow.
'''
import argparse
import os
from PIL import Image
def find_dir(path):
'''
Create target directory if it does not exist.
'''
if not os.path.exists(path):
os.makedirs(path)
def analyze_image(path):
'''
Pre-process the image to determine the mode (full or additive).
'''
image = Image.open(path)
results = {'size': image.size, 'mode': 'full'}
try:
while True:
if image.tile:
tile = image.tile[0]
update_region = tile[1]
update_region_dimensions = update_region[2:]
if update_region_dimensions != image.size:
results['mode'] = 'partial'
break
image.seek(image.tell()+1)
except EOFError:
pass
return results
def process_image(path):
'''
Iterate through the frames in GIF, extracting each frame.
'''
mode = analyze_image(path)['mode']
image = Image.open(path)
i = 0
palette = image.getpalette()
last_frame = image.convert('RGBA')
new_dir = ''.join(os.path.basename(path).split('.')[:-1])
find_dir(new_dir)
try:
while True:
print('Saving {:} ({:}) frame {:}, {:} {:}'
.format(path, mode, i, image.size, image.tile))
if not image.getpalette():
image.putpalette(palette)
new_frame = Image.new('RGBA', image.size)
if mode == 'partial':
new_frame.paste(last_frame)
new_frame.paste(image, (0, 0), image.convert('RGBA'))
new_path = '{:}/{:}.png'.format(new_dir, i)
new_frame.save(new_path, 'PNG')
i += 1
last_frame = new_frame
image.seek(image.tell()+1)
except EOFError:
pass
def get_file_path():
'''
Get the file path from command line.
'''
# Setup the parser.
parser = argparse.ArgumentParser(description='Extract .gif into frames.')
parser.add_argument('filePath', help='Path to the file.')
# Retrieve the filenames.
args = parser.parse_args()
return args.filePath
def main():
'''
The main function, wrapped to avoid global variable issue.
'''
path = get_file_path()
process_image(path)
if __name__ == '__main__':
main()