Pillow/Scripts/gifmaker.py
Hugo b816c048ad Merge pull request #1172 from radarhere/gif
Added duration and loop set to GifImagePlugin
2015-06-04 13:07:58 +03:00

142 lines
3.0 KiB
Python

#!/usr/bin/env python
#
# The Python Imaging Library
# $Id$
#
# convert sequence format to GIF animation
#
# history:
# 97-01-03 fl created
#
# Copyright (c) Secret Labs AB 1997. All rights reserved.
# Copyright (c) Fredrik Lundh 1997.
#
# See the README file for information on usage and redistribution.
#
#
# For special purposes, you can import this module and call
# the makedelta or compress functions yourself. For example,
# if you have an application that generates a sequence of
# images, you can convert it to a GIF animation using some-
# thing like the following code:
#
# import Image
# import gifmaker
#
# sequence = []
#
# # generate sequence
# for i in range(100):
# im = <generate image i>
# sequence.append(im)
#
# # write GIF animation
# fp = open("out.gif", "wb")
# gifmaker.makedelta(fp, sequence)
# fp.close()
#
# Alternatively, use an iterator to generate the sequence, and
# write data directly to a socket. Or something...
#
from __future__ import print_function
from PIL import Image, ImageChops
from PIL.GifImagePlugin import getheader, getdata
# --------------------------------------------------------------------
# sequence iterator
class image_sequence(object):
def __init__(self, im):
self.im = im
def __getitem__(self, ix):
try:
if ix:
self.im.seek(ix)
return self.im
except EOFError:
raise IndexError # end of sequence
# --------------------------------------------------------------------
# straightforward delta encoding
def makedelta(fp, sequence):
"""Convert list of image frames to a GIF animation file"""
frames = 0
previous = None
for im in sequence:
# To specify duration, add the time in milliseconds to getdata(),
# e.g. getdata(im, duration=1000)
if not previous:
# global header
for s in getheader(im)[0] + getdata(im):
fp.write(s)
else:
# delta frame
delta = ImageChops.subtract_modulo(im, previous)
bbox = delta.getbbox()
if bbox:
# compress difference
for s in getdata(im.crop(bbox), offset=bbox[:2]):
fp.write(s)
else:
# FIXME: what should we do in this case?
pass
previous = im.copy()
frames += 1
fp.write(";")
return frames
# --------------------------------------------------------------------
# main hack
def compress(infile, outfile):
# open input image, and force loading of first frame
im = Image.open(infile)
im.load()
# open output file
fp = open(outfile, "wb")
seq = image_sequence(im)
makedelta(fp, seq)
fp.close()
if __name__ == "__main__":
import sys
if len(sys.argv) < 3:
print("GIFMAKER -- create GIF animations")
print("Usage: gifmaker infile outfile")
sys.exit(1)
compress(sys.argv[1], sys.argv[2])