[PYTHON IMAGE-SIG] GIF animations in Grail

Fred L. Drake fdrake@CNRI.Reston.Va.US
Fri, 4 Apr 1997 14:19:47 -0500 (EST)


  Here's a filetype handler for Grail that does GIF animations for GIF
files loaded as documents; this doesn't handle "in-line" GIFs.
(Sorry!)
  Save this as ~/.grail/filetypes/image_gif.py, and make sure the file
Grail/pil_interface.py from the PIL distribution is available for
Grail (it can be placed in the same directory).


  -Fred

--
Fred L. Drake, Jr.
fdrake@cnri.reston.va.us
Corporation for National Research Initiatives
1895 Preston White Drive
Reston, VA    20191-5434


===========================================================================
# Grail interface to PIL, with support for animated GIFs.

import grailutil
import Image
import ImageTk
import pil_interface
import string
import StringIO
import sys
import Tkinter

class parse_image_gif(pil_interface.pil_interface):

    im = None
    currentpos = 0
    duration = 0
    loop = 0

    def close(self):
	if self.buf:
	    try:
		self.label.config(text="<decoding>")
		self.label.update_idletasks()
		self.buf = string.joinfields(self.buf, "")
		self.im = im = Image.open(StringIO.StringIO(self.buf))
		im.load() # benchmark decoding
		self.tkim = tkim = ImageTk.PhotoImage(im.mode, im.size)
		tkim.paste(im)
		self.label.image = tkim.image
		self.label.config(image=self.label.image)
		if im.info.has_key("duration"):
		    self.duration = im.info["duration"]
		if im.info.has_key("loop"):
		    self.duration = self.duration or 100
		    self.loop = im.info["loop"]
		if self.duration or self.loop:
		    self.viewer.register_reset_interest(self.cancel_loop)
		    self.after_id = self.label.after(self.duration,
						     self.next_image)
	    except:
		self.broken = 1
		stdout = sys.stdout
		try:
		    sys.stdout = sys.stderr
		    print "Error decoding image:"
		    print sys.exc_type + ":", sys.exc_value
		finally:
		    sys.stdout = stdout
	if self.broken:
	    self.label.image = Tkinter.PhotoImage(
		file=grailutil.which(ERROR_FILE))
	    self.label.config(image = self.label.image)
	    self.viewer.text.insert(Tkinter.END, '\nBroken Image!')

    def next_image(self):
	newpos = self.currentpos + 1
	try:
	    self.im.seek(newpos)
	except (ValueError, EOFError):
	    self.viewer.unregister_reset_interest(self.cancel_loop)
	    return			# ignore looping for now....
	self.currentpos = newpos
	self.tkim.paste(self.im)
	self.after_id = self.label.after(self.duration, self.next_image)

    def cancel_loop(self, *args):
	self.viewer.unregister_reset_interest(self.cancel_loop)
	self.label.after_cancel(self.after_id)

_______________
IMAGE-SIG - SIG on Image Processing with Python

send messages to: image-sig@python.org
administrivia to: image-sig-request@python.org
_______________