Sunday 15 January 2012

python - Displaying animated GIFs in Tkinter using PIL -


I'm trying to create a program to use an animated GIF using tininkers here I have the basic form Used to:

  __future__ from the import partition # just because the partition does not work properly in 2.7.4. Import from TIL importer from PIL import * Image, imported import imported timing from import timing (name): ## Returns ('frames', 'delay', 'loc', 'len'} im = Image.open (name) Gif = {'frames': [], 'delay': 100, 'folk': 0, 'lane': 0} picture = [] try: while correct: pics.append (im.copy ()) im.seek Except for len (pics): EOFError: pass temp = pics [0]. ([RGBA] GIF ['frame'] = [image tag] Photo image (temporary)] Temporary = Picture [0] For items in pictures [1:]: Temp.paste (item) GIF ['frame'] .append (temp.photoImage (temp.convert ('RGBA')) Try: gif ['delay'] = im.info ['duration' ] Except: pass gif [' Returns GIF Deaf Ratio (A, B): If B & L; A: d, c = a, b Other: c, d = a, b if b == A: Back in i for i (xchange (2, int (round (a / 2)): if a = I == 0 and b% i == 0: a / = ib / = i (int (a ), Int (b) class app (frame): def show (self, image = none, event = none): self.display.create_image ((0,0), anchor = NW, image = image) def Chetan (self, incident = none): self.show (image = self.gif ['frame'] [self. Gif ['folk']]) self.gif ['loc'] + = 1 if self.gif ['loc'] == self. Gif ['len']: self.gif ['loc'] = 0 if self.cont: threading.Timer (self .gif ['delay'] / 1000), self. Final). Start (def def kill (self, event = none): self.cont = wrong sleep (0.1) self Apple () def __init __ (self, master): frame .__ init __ (self, master) self Self.rowconfigure (1, weight = 2) self.rowconfigure (3, weight = 1) self.columnconfigure (0, weight = 1) self.title = grid (line = 0, stick = n + e + s + w) Label (self, text = 'no title') self.title.grid (line = 0, sticky = e + w) self Display = canvas (self) self Display.grid (line = 1, stick = = n + e + s + w) self.user = label (self, text = 'posted by a user' ') self.user.grid (line = 2, sticky = E + w) self .comment = Text (self, height = 4, width = 40, state = disabled) self.comment.grid (row = 3, sticky = N + E + S + W) self.cont = true self .gif = anim_gif ('Test.gif') self.animate () root.protocol ("WM_DELETE_WINDOW", self. Kill) root = Tk () root.rowconfigure (0, weight = 1) root.columnconfigure (0, weight = 1) App = App (root) app Mainloop () Try: Excluding root.destroy (): Pass   

test.gif is the following GIF:

 Enter the image details here

It works fine, but GIF quality is terrible. I tried to change it: Gif = {'frames': [], 'defame' Delay: 100, 'loc': 0, 'len': 0} pics = [] Try: While correct: GIF ['frame']. Copy ()) im.seek (len (gif ['frame'])) Except EOFError: Try nearby: except GIF ['delay'] = im.info ['duration']: near GIF ['lane '] = LAN (GIF [' frame ']) Return GIF Class app (frame): Def Show (self, image = none, event = none): can_w = self.display [' width '] can_h = self Display ['height'] Pic_w, pic_h = image.size rat_w, rat_h = ratio (pic_w, pic_h) while pic_w & gt; Int (can_w) or pic_h & gt; Int (can_h): pic_w - = rat_w pic_h - = rat_h resized = image.resize ((pic_w, pic_h)) resized = ImageTk.PhotoImage (resized) self.display.create_image ((0,0), anchor = nw, image = Resized)

However, this will sometimes flash the image. While the picture looks good, it is very worthless as a program. What am I doing wrong?

For one, you are creating a new canvas object for each frame. After all, you have thousands of images at the top of each other, it is highly inefficient; There are performance issues in the canvas widget when you start thousands of objects.

Instead of creating a new image object on the canvas, simply reconfigure the existing object with the canvas method.

Secondly, you do not need threading complications for such a simple task. There is a well known pattern in the tanker to create an animation: Draw a frame, then use that function after to call in the future to call itself.

Something like this:

  def Chetan (Self): If self._image_id is none: self._image_id = self.display.create_image (...) Other: Self.itemconfig (self._image_id, image = the_new_image) self.display.after (self.gif ["delay"], itself.)   

Finally, unless a strict reason Do not use canvas, you can reduce the complexity by using a label widget.

No comments:

Post a Comment