Skip to content

Instantly share code, notes, and snippets.

@0xpizza
Last active January 27, 2022 22:59
Show Gist options
  • Save 0xpizza/b11b830edd1c30f87fabc69fae7270df to your computer and use it in GitHub Desktop.
Save 0xpizza/b11b830edd1c30f87fabc69fae7270df to your computer and use it in GitHub Desktop.
#!python3.9
import itertools
import tkinter as tk
from pathlib import Path
class AnimatedGif(tk.Canvas):
"""
Loads an GIF file and renders its frames
using the Tk event loop.
"""
def __init__(self, master=None, **kwargs):
image = kwargs.pop('image')
if isinstance(image, str):
self._image_data = Path(image).read_bytes()
elif isinstance(image, bytes):
self._image_data = image
else:
raise TypeError(
f'Unsupported type: {image!r}.'
f'Must be {str!r} or {bytes!r}'
)
self._gif_frames = None
self._gif_frame_tags = None
self._fps = 24
super().__init__(master, **kwargs)
self.config(highlightthickness=0)
self._build_frames()
self._configure_layers()
self.after(1, self._loop_gif)
def _configure_layers(self):
frames = self._gif_frames
tags = []
self.configure(
width=frames[0].width(),
height=frames[0].height(),
)
for i, frame in enumerate(frames):
tag = str(i)
self.create_image(
0, 0,
image=frame,
anchor=tk.NW,
tags=tag,
)
tags.append(tag)
self._gif_frame_tags = itertools.cycle(tags)
def _loop_gif(self):
self.tag_raise(
next(self._gif_frame_tags)
)
self.after(self._fps, self._loop_gif)
def _build_frames(self):
#TODO: make this method faster!!
frames = []
for i in range(1000):
try:
frames.append(
tk.PhotoImage(
data=self._image_data,
format=f'gif -index {i}'
))
except tk.TclError as e:
if 'no image data for this index' in str(e):
break
raise e
self._gif_frames = frames
def main():
from urllib.request import urlopen
url = (
'https://upload.wikimedia.org/wikipedia/commons/2/'
'2c/Rotating_earth_%28large%29.gif'
)
path = Path.home() / 'earth.gif'
if not path.exists():
path.write_bytes(urlopen(url).read())
r = tk.Tk()
Gif(r, image=str(path)).pack()
r.mainloop()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment