Adafruit_Learning_System_Gu.../Raspberry_Pi_Animated_Gif_Player/animatedgif.py
Melissa LeBlanc-Williams c39010a8ad Add Rotary Gif Players
2021-09-24 10:36:12 -07:00

122 lines
4.1 KiB
Python

import os
import time
from PIL import Image, ImageOps
# pylint: disable=too-few-public-methods
class Frame:
def __init__(self, duration=0):
self.duration = duration
self.image = None
# pylint: enable=too-few-public-methods
class AnimatedGif:
def __init__(self, display, include_delays=True, folder=None):
self._frame_count = 0
self._loop = 0
self._index = 0
self._duration = 0
self._gif_files = []
self._frames = []
self._running = True
self.display = display
self.include_delays = include_delays
if folder is not None:
self.load_files(folder)
self.run()
def advance(self):
self._index = (self._index + 1) % len(self._gif_files)
def back(self):
self._index = (self._index - 1 + len(self._gif_files)) % len(self._gif_files)
def load_files(self, folder):
gif_files = [f for f in os.listdir(folder) if f.endswith(".gif")]
gif_folder = folder
if gif_folder[:-1] != "/":
gif_folder += "/"
for gif_file in gif_files:
image = Image.open(gif_folder + gif_file)
# Only add animated Gifs
if image.is_animated:
self._gif_files.append(gif_folder + gif_file)
print("Found", self._gif_files)
if not self._gif_files:
print("No Gif files found in current folder")
exit() # pylint: disable=consider-using-sys-exit
def preload(self):
image = Image.open(self._gif_files[self._index])
print("Loading {}...".format(self._gif_files[self._index]))
if "duration" in image.info:
self._duration = image.info["duration"]
else:
self._duration = 0
if "loop" in image.info:
self._loop = image.info["loop"]
else:
self._loop = 1
self._frame_count = image.n_frames
self._frames.clear()
for frame in range(self._frame_count):
image.seek(frame)
# Create blank image for drawing.
# Make sure to create image with mode 'RGB' for full color.
frame_object = Frame(duration=self._duration)
if "duration" in image.info:
frame_object.duration = image.info["duration"]
frame_object.image = ImageOps.pad( # pylint: disable=no-member
image.convert("RGB"),
(self._width, self._height),
method=Image.NEAREST,
color=(0, 0, 0),
centering=(0.5, 0.5),
)
self._frames.append(frame_object)
def play(self):
self.preload()
current_frame = 0
last_action = None
# Check if we have loaded any files first
if not self._gif_files:
print("There are no Gif Images loaded to Play")
return False
self.update_display(self._frames[current_frame].image)
while self._running:
action = self.get_next_value()
if action:
if not last_action:
last_action = action
if action == "click":
self.advance()
return False
elif int(action) < int(last_action):
current_frame -= 1
else:
current_frame += 1
current_frame %= self._frame_count
frame_object = self._frames[current_frame]
start_time = time.monotonic()
self.update_display(frame_object.image)
if self.include_delays:
remaining_delay = frame_object.duration / 1000 - (
time.monotonic() - start_time
)
if remaining_delay > 0:
time.sleep(remaining_delay)
last_action = action
if self._loop == 1:
return True
if self._loop > 0:
self._loop -= 1
def run(self):
while self._running:
auto_advance = self.play()
if auto_advance:
self.advance()