参考URL
[http://pastebin.com/Rr7dAxbF]
[http://www.tohoho-web.com/wwwgif.htm]
[http://www.marguerite.jp/Nihongo/Labo/Image/GIF.html]
agif.py
# -*- coding: utf-8 -*-
import struct
import math
from cStringIO import StringIO
from PIL import Image, GifImagePlugin
class AGIF(object):
"""
>>> from PIL import ImageDraw, ImageFont
>>> agif = AGIF(4)
>>> size = (80, 15)
>>> img = Image.new("RGB", size, "white")
>>> draw = ImageDraw.Draw(img)
>>> text = "Hello, world!"
>>> for i in range(len(text)):
... draw.rectangle((0, 0) + size, fill="white")
... draw.text((0, 0), text[:i], fill="black")
... agif.paste(img, duration=0.2)
>>> agif.save("example1.gif")
>>> import urllib
>>> from cStringIO import StringIO
>>> from PIL import ImageOps
>>> url = "http://www.python.org/community/logos/python-powered-h-140x182.png"
>>> istream = StringIO(urllib.urlopen(url).read())
>>> image = Image.open(istream)
>>> square = ImageOps.fit(image, (240, 240))
>>> agif = AGIF(128)
>>> for i in range(0, 360, 5):
... agif.paste(square.rotate(i), 0.03)
>>> agif.save("example2.gif")
"""
def __init__(self, colors, loop=0):
assert colors in [2, 4, 8, 16, 32, 64, 128, 256]
self.colors = colors
self.loop = loop
self.buf = StringIO()
self.pasted = False
def paste(self, image, duration=0.1):
image = self._convert_to_gif(image)
if not self.pasted:
self._write_header(image)
self._write_image(image, duration)
self.pasted = True
def save(self, file):
if isinstance(file, basestring):
file = open(file, "w")
self.buf.seek(0)
file.writelines(self.buf)
file.write("\x3b")
def _convert_to_gif(self, image):
"""半透明なPNG画像を白色の背景とマージする"""
if image.mode == "RGBA":
merged = Image.new("RGBA", image.size, (255, 255, 255, 0))
merged.paste(image, (0, 0) + image.size, image)
image = merged.convert("RGB")
return image.convert("P", palette=Image.ADAPTIVE, colors=self.colors)
def _write_header(self, image):
buf = self.buf
buf.write("GIF89a")
width, height = image.size
buf.write(struct.pack("< H", width))
buf.write(struct.pack("< H", height))
buf.write(chr(0xe0 | int(math.log(self.colors, 2) - 1)))
buf.write("\x00\x00")
buf.write(GifImagePlugin.getheader(image)[1][:self.colors*3])
buf.write("\x21\xff\x0bNETSCAPE2.0")
if self.loop == 0:
buf.write("\x03\x01\x00\x00")
elif self.loop != 1:
buf.write("\x03\x01")
buf.write(struct.pack("< H", self.loop-1))
buf.write("\x00")
def _write_image(self, image, duration):
buf = self.buf
buf.write("\x21\xf9\x04\x08")
buf.write(struct.pack("< H", duration * 100))
buf.write("\x00\x00")
if self.pasted:
data = GifImagePlugin.getdata(image)
header = list(data[0])
header[-2] = chr(128 | int(math.log(self.colors, 2) - 1))
buf.write("".join(header)[:-1])
buf.write(GifImagePlugin.getheader(image)[1][:self.colors*3])
buf.write(header[-1])
for d in data[1:]:
buf.write(d)
else:
for d in GifImagePlugin.getdata(image):
buf.write(d)
if __name__ == '__main__':
import doctest
doctest.testmod()