Skip to content

Commit 070c9ec

Browse files
authored
Merge pull request #57 from makermelissa/master
Added Support for variable duration Gifs and image resizing
2 parents 68cf38a + b3a7d57 commit 070c9ec

File tree

1 file changed

+55
-16
lines changed

1 file changed

+55
-16
lines changed

examples/rgb_display_pillow_animated_gif.py

+55-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import time
1616
import digitalio
1717
import board
18-
from PIL import Image
18+
from PIL import Image, ImageDraw
1919
import adafruit_rgb_display.ili9341 as ili9341
2020
import adafruit_rgb_display.st7789 as st7789 # pylint: disable=unused-import
2121
import adafruit_rgb_display.hx8357 as hx8357 # pylint: disable=unused-import
@@ -34,14 +34,30 @@ def init_button(pin):
3434
button.pull = digitalio.Pull.UP
3535
return button
3636

37+
# pylint: disable=too-few-public-methods
38+
class Frame:
39+
def __init__(self, duration=0):
40+
self.duration = duration
41+
self.image = None
42+
# pylint: enable=too-few-public-methods
43+
3744
class AnimatedGif:
38-
def __init__(self, display, folder=None):
45+
def __init__(self, display, width=None, height=None, folder=None):
3946
self._frame_count = 0
4047
self._loop = 0
4148
self._index = 0
42-
self._delay = 0
49+
self._duration = 0
4350
self._gif_files = []
4451
self._frames = []
52+
53+
if width is not None:
54+
self._width = width
55+
else:
56+
self._width = disp.width
57+
if height is not None:
58+
self._height = height
59+
else:
60+
self._height = disp.height
4561
self.display = display
4662
self.advance_button = init_button(board.D17)
4763
self.back_button = init_button(board.D22)
@@ -71,22 +87,45 @@ def load_files(self, folder):
7187
def preload(self):
7288
image = Image.open(self._gif_files[self._index])
7389
print("Loading {}...".format(self._gif_files[self._index]))
74-
self._delay = image.info['duration']
90+
if "duration" in image.info:
91+
self._duration = image.info['duration']
92+
else:
93+
self._duration = 0
7594
if "loop" in image.info:
7695
self._loop = image.info['loop']
7796
else:
7897
self._loop = 1
7998
self._frame_count = image.n_frames
99+
screen_ratio = self._width / self._height
100+
image_ratio = image.width / image.height
101+
if screen_ratio > image_ratio:
102+
scaled_width = image.width * self._height // image.height
103+
scaled_height = self._height
104+
else:
105+
scaled_width = self._width
106+
scaled_height = image.height * self._width // image.width
80107

81108
self._frames.clear()
82109
for frame in range(self._frame_count):
83110
image.seek(frame)
84111
# Create blank image for drawing.
85112
# Make sure to create image with mode 'RGB' for full color.
86-
frame_image = Image.new('RGB', (width, height))
87-
frame_image.paste(image, (width // 2 - image.width // 2,
88-
height // 2 - image.height // 2))
89-
self._frames.append(frame_image)
113+
frame_object = Frame(duration=self._duration)
114+
if "duration" in image.info:
115+
frame_object.duration = image.info['duration']
116+
frame_object.image = Image.new('RGB', (self._width, self._height))
117+
118+
# Get drawing object to draw on image.
119+
draw = ImageDraw.Draw(frame_object.image)
120+
draw.rectangle((0, 0, self._width, self._height), outline=0, fill=(0, 0, 0))
121+
122+
frame_image = image.copy()
123+
frame_image = frame_image.resize((scaled_width, scaled_height), Image.BICUBIC)
124+
x = scaled_width // 2 - self._width // 2
125+
y = scaled_height // 2 - self._height // 2
126+
frame_image = frame_image.crop((x, y, x + self._width, y + self._height))
127+
frame_object.image.paste(frame_image)
128+
self._frames.append(frame_object)
90129

91130
def play(self):
92131
self.preload()
@@ -95,13 +134,13 @@ def play(self):
95134
if not self._gif_files:
96135
print("There are no Gif Images to Play")
97136

98-
for frame_image in self._frames:
99-
self.display.image(frame_image)
137+
for frame_object in self._frames:
138+
self.display.image(frame_object.image)
100139
if not self.advance_button.value:
101140
self.advance()
102141
elif not self.back_button.value:
103142
self.back()
104-
time.sleep(self._delay / 1000)
143+
time.sleep(frame_object.duration / 1000)
105144

106145
if self._loop == 1:
107146
return
@@ -136,10 +175,10 @@ def run(self):
136175
# pylint: enable=line-too-long
137176

138177
if disp.rotation % 180 == 90:
139-
height = disp.width # we swap height/width to rotate it to landscape!
140-
width = disp.height
178+
disp_height = disp.width # we swap height/width to rotate it to landscape!
179+
disp_width = disp.height
141180
else:
142-
width = disp.width # we swap height/width to rotate it to landscape!
143-
height = disp.height
181+
disp_width = disp.width # we swap height/width to rotate it to landscape!
182+
disp_height = disp.height
144183

145-
gif_player = AnimatedGif(disp, ".")
184+
gif_player = AnimatedGif(disp, width=disp_width, height=disp_height, folder=".")

0 commit comments

Comments
 (0)