Advertisement
Guest User

WillP's refactored images2gif.py (based on Almar Klein's)

a guest
Mar 10th, 2013
973
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.27 KB | None | 0 0
  1. """ MODULE images2gif
  2.  
  3. Provides a function (writeGif) to write animated gif from a series
  4. of PIL images
  5.  
  6. This code is provided as is, and is free to use for all.
  7.  
  8. Almar Klein (June 2009)
  9. Will Pierce (March 2013) - removed numpy support and refactored internals
  10.  
  11. - based on gifmaker (in the scripts folder of the source distribution of PIL)
  12. - based on gif file structure as provided by wikipedia
  13. """
  14.  
  15. import struct
  16. import PIL
  17. from PIL import Image
  18. from PIL.GifImagePlugin import getheader, getdata
  19.  
  20. # getheader gives a 87a header and a color palette (two elements in a list).
  21. # getdata()[0] gives the Image Descriptor up to (including) "LZW min code size".
  22. # getdatas()[1:] is the image data itself in chuncks of 256 bytes (well
  23. # technically the first byte says how many bytes follow, after which that
  24. # amount (max 255) follows).
  25.  
  26. intToBin = struct.Struct('<H').pack
  27.  
  28. def getheaderAnim(im):
  29.   """ Animation header. To replace the getheader()[0] """
  30.   return ''.join(["GIF89a",
  31.                   intToBin(im.size[0]),
  32.                   intToBin(im.size[1]),
  33.                   "\x87\x00\x00"])
  34.  
  35. def getAppExt(loops):
  36.   """ Application extention. Part that secifies amount of loops.
  37.  if loops is 0, it goes on infinitely.
  38.  """
  39.   return ''.join(["\x21\xFF\x0B",  # application extension
  40.                   "NETSCAPE2.0",
  41.                   "\x03\x01",
  42.                   intToBin(loops),
  43.                   '\x00'])  # end
  44.  
  45. def getGraphicsControlExt(duration=0.1):
  46.   """ Graphics Control Extension. A header at the start of
  47.  each image. Specifies transparancy and duration. """
  48.   return ''.join(['\x21\xF9\x04',
  49.                   '\x08',  # no transparency
  50.                   intToBin(int(duration * 100)), # in 100th of seconds
  51.                   '\x00',  # no transparent color
  52.                   '\x00'])  # end
  53.  
  54. def _writeGifToFile(fp, images, durations, loops):
  55.   """ Given a set of images writes the bytes to the specified stream."""
  56.   # first image, gather data for global header
  57.   img = images[0]
  58.   header = getheaderAnim(img)
  59.   palette = getheader(img)[1]
  60.   appext = getAppExt(loops)
  61.  
  62.   # output the initial header
  63.   fp.write(header)
  64.   fp.write(palette)
  65.   fp.write(appext)
  66.  
  67.   # write sequence of images
  68.   for img, duration in zip(images, durations):
  69.     graphext = getGraphicsControlExt(duration)
  70.     fp.write(graphext)
  71.     for dat in getdata(img):
  72.       fp.write(dat)
  73.   fp.write(';')  # end gif marker
  74.  
  75. def writeGif(filename, images, duration=0.1, loops=0, dither=1):
  76.     """Write an animated gif from the specified images.
  77.    
  78.    @param str filename - output filename
  79.    @param list images - a list of PIL Images
  80.    @param int/list duration - either a float for per-frame delay, or list of floats
  81.    @param int loops - number of times the animation should loop, None means infinite
  82.    @param int dither - dithering mode for Image.convert(), set to 0 to disable dithering
  83.    """
  84.     # build duration list
  85.     try:
  86.       assert len(duration) == len(images)
  87.       durations = duration
  88.     except TypeError:
  89.       durations = [duration] * len(images)
  90.      
  91.     # convert to PIL gifs (palette mode)
  92.     gifs = [img.convert('P', dither=dither) for img in images]
  93.  
  94.     with open(filename, 'wb') as fp:
  95.       _writeGifToFile(fp, gifs, durations, loops)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement