Skip to content

Initial commit of PiTFT Animated Gif Player #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jan 3, 2020
144 changes: 144 additions & 0 deletions examples/rgb_display_pillow_animated_gif.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
"""
Example to extract the frames and other parameters from an animated gif
and then run the animation on the display.

Usage:
python3 rgb_display_pillow_animated_gif.py

This example is for use on (Linux) computers that are using CPython with
Adafruit Blinka to support CircuitPython libraries. CircuitPython does
not support PIL/pillow (python imaging library)!

Author(s): Melissa LeBlanc-Williams for Adafruit Industries
"""
import os
import time
import digitalio
import board
from PIL import Image
import adafruit_rgb_display.ili9341 as ili9341
import adafruit_rgb_display.st7789 as st7789 # pylint: disable=unused-import
import adafruit_rgb_display.hx8357 as hx8357 # pylint: disable=unused-import
import adafruit_rgb_display.st7735 as st7735 # pylint: disable=unused-import
import adafruit_rgb_display.ssd1351 as ssd1351 # pylint: disable=unused-import
import adafruit_rgb_display.ssd1331 as ssd1331 # pylint: disable=unused-import

# Configuration for CS and DC pins (these are PiTFT defaults):
cs_pin = digitalio.DigitalInOut(board.CE0)
dc_pin = digitalio.DigitalInOut(board.D25)
reset_pin = digitalio.DigitalInOut(board.D24)

def init_button(pin):
button = digitalio.DigitalInOut(pin)
button.switch_to_input()
button.pull = digitalio.Pull.UP
return button

class AnimatedGif:
def __init__(self, display, folder=None):
self._frame_count = 0
self._loop = 0
self._index = 0
self._delay = 0
self._gif_files = []
self._frames = []
self.display = display
self.advance_button = init_button(board.D17)
self.back_button = init_button(board.D22)
if folder is not None:
self.load_files(folder)
self.run()

def advance(self, loop=False):
if self._index < len(self._gif_files) - 1:
self._index += 1
elif loop and self._index == len(self._gif_files) - 1:
self._index = 0

def back(self, loop=False):
if self._index > 0:
self._index -= 1
elif loop and self._index == 0:
self._index = len(self._gif_files) - 1

def load_files(self, folder):
self._gif_files = [f for f in os.listdir(folder) if f[-4:] == '.gif']
print("Found", self._gif_files)
if not self._gif_files:
print("No Gif files found in current folder")
exit()

def preload(self):
image = Image.open(self._gif_files[self._index])
print("Loading {}...".format(self._gif_files[self._index]))
self._delay = image.info['duration']
if "loop" in image.info:
self._loop = image.info['loop']
else:
self._loop = 1
self._frame_count = image.n_frames

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_image = Image.new('RGB', (width, height))
frame_image.paste(image, (width // 2 - image.width // 2,
height // 2 - image.height // 2))
self._frames.append(frame_image)

def play(self):
self.preload()

# Check if we have loaded any files first
if not self._gif_files:
print("There are no Gif Images to Play")

for frame_image in self._frames:
self.display.image(frame_image)
if not self.advance_button.value:
self.advance()
elif not self.back_button.value:
self.back()
time.sleep(self._delay / 1000)

if self._loop == 1:
return
if self._loop > 0:
self._loop -= 1

def run(self):
while True:
self.play()
self.advance(True)

# Config for display baudrate (default max is 24mhz):
BAUDRATE = 64000000

# Setup SPI bus using hardware SPI:
spi = board.SPI()

# pylint: disable=line-too-long
# Create the display:
#disp = st7789.ST7789(spi, rotation=90 # 2.0" ST7789
#disp = st7789.ST7789(spi, height=240, y_offset=80, rotation=90 # 1.3", 1.54" ST7789
#disp = st7789.ST7789(spi, rotation=90, width=135, height=240, x_offset=53, y_offset=40, # 1.14" ST7789
#disp = hx8357.HX8357(spi, rotation=180, # 3.5" HX8357
#disp = st7735.ST7735R(spi, rotation=90, # 1.8" ST7735R
#disp = st7735.ST7735R(spi, rotation=270, height=128, x_offset=2, y_offset=3, # 1.44" ST7735R
#disp = st7735.ST7735R(spi, rotation=90, bgr=True, # 0.96" MiniTFT ST7735R
#disp = ssd1351.SSD1351(spi, rotation=180, # 1.5" SSD1351
#disp = ssd1351.SSD1351(spi, height=96, y_offset=32, rotation=180, # 1.27" SSD1351
#disp = ssd1331.SSD1331(spi, rotation=180, # 0.96" SSD1331
disp = ili9341.ILI9341(spi, rotation=90, # 2.2", 2.4", 2.8", 3.2" ILI9341
cs=cs_pin, dc=dc_pin, rst=reset_pin, baudrate=BAUDRATE)
# pylint: enable=line-too-long

if disp.rotation % 180 == 90:
height = disp.width # we swap height/width to rotate it to landscape!
width = disp.height
else:
width = disp.width # we swap height/width to rotate it to landscape!
height = disp.height

gif_player = AnimatedGif(disp, ".")