Add gifplay.py, fix other scripts for python3
This commit is contained in:
parent
13d7a994b9
commit
476e446c25
4 changed files with 121 additions and 10 deletions
16
bargraph.py
16
bargraph.py
|
|
@ -16,9 +16,9 @@ BACKGROUND_COLOR = (0, 0, 0)
|
|||
HOUR_FOREGROUND = (255, 0, 0)
|
||||
MINUTE_FOREGROUND = (255, 255, 0)
|
||||
SECOND_FOREGROUND = (0, 255, 0)
|
||||
HOUR_BACKGROUND = tuple(i/8 for i in HOUR_FOREGROUND)
|
||||
MINUTE_BACKGROUND = tuple(i/8 for i in MINUTE_FOREGROUND)
|
||||
SECOND_BACKGROUND = tuple(i/8 for i in SECOND_FOREGROUND)
|
||||
HOUR_BACKGROUND = tuple(i//8 for i in HOUR_FOREGROUND)
|
||||
MINUTE_BACKGROUND = tuple(i//8 for i in MINUTE_FOREGROUND)
|
||||
SECOND_BACKGROUND = tuple(i//8 for i in SECOND_FOREGROUND)
|
||||
|
||||
class BargraphClock(SpectroBase):
|
||||
"""Bargraph clock for Spectro."""
|
||||
|
|
@ -51,16 +51,16 @@ class BargraphClock(SpectroBase):
|
|||
localtime = time.localtime(time.time())
|
||||
if TWELVE_HOUR == True:
|
||||
hour = localtime.tm_hour % 12
|
||||
width = 44 * (hour * 60 + localtime.tm_min) / 719
|
||||
width = 44 * (hour * 60 + localtime.tm_min) // 719
|
||||
if hour == 0:
|
||||
hour = 12
|
||||
else:
|
||||
hour = localtime.tm_hour
|
||||
width = 44 * (hour * 60 + localtime.tm_min) / 1439
|
||||
width = 44 * (hour * 60 + localtime.tm_min) // 1439
|
||||
|
||||
self.draw_digit(hour / 10, 2, 2)
|
||||
self.draw_digit(hour // 10, 2, 2)
|
||||
self.draw_digit(hour % 10, 10, 2)
|
||||
self.draw_digit(localtime.tm_min / 10, 2, 14)
|
||||
self.draw_digit(localtime.tm_min // 10, 2, 14)
|
||||
self.draw_digit(localtime.tm_min % 10, 10, 14)
|
||||
|
||||
if width > 0:
|
||||
|
|
@ -68,7 +68,7 @@ class BargraphClock(SpectroBase):
|
|||
if width < 44:
|
||||
draw.rectangle((18 + width, 2, 61, 11), fill=HOUR_BACKGROUND)
|
||||
|
||||
width = 44 * localtime.tm_min / 59
|
||||
width = 44 * localtime.tm_min // 59
|
||||
if width > 0:
|
||||
draw.rectangle((18, 14, 17 + width, 23), fill=MINUTE_FOREGROUND)
|
||||
if width < 44:
|
||||
|
|
|
|||
110
gifplay.py
Executable file
110
gifplay.py
Executable file
|
|
@ -0,0 +1,110 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
GIF player for Adafruit Spectro.
|
||||
"""
|
||||
|
||||
import os
|
||||
import glob
|
||||
import time
|
||||
from PIL import Image, ImageSequence
|
||||
from spectrobase import SpectroBase
|
||||
|
||||
DEFAULT_GIF_PATH = "/boot/gifs"
|
||||
LOOP_TIME = 10
|
||||
FILTER = Image.LANCZOS # Slower Pis might want BICUBIC or BILINEAR here
|
||||
|
||||
class GIFplayer(SpectroBase):
|
||||
"""GIF player for Adafruit Spectro."""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GIFplayer, self).__init__(*args, **kwargs)
|
||||
|
||||
self.gif_path = DEFAULT_GIF_PATH
|
||||
self.matrix_size = None
|
||||
self.double_buffer = None
|
||||
self.frame_start_time = 0
|
||||
self.frame_duration = 0
|
||||
|
||||
self.parser.add_argument(
|
||||
"-d", "--dir", help="Directory containing GIFs",
|
||||
default=DEFAULT_GIF_PATH)
|
||||
|
||||
def loop_gif(self, image):
|
||||
"""Play one image for LOOP_TIME seconds or one complete pass,
|
||||
whichever is longer."""
|
||||
file_start_time = time.time()
|
||||
|
||||
# Determine how to size and center image on the matrix,
|
||||
# maintaining the aspect ratio (approximately, due to resolution).
|
||||
matrix_aspect = float(self.matrix.width) / float(self.matrix.height)
|
||||
image_aspect = float(image.width) / float(image.height)
|
||||
if matrix_aspect > image_aspect:
|
||||
# Letterbox horizontally (vertical bars left/right)
|
||||
scaled_size = (int(self.matrix.height * image_aspect + 0.5),
|
||||
self.matrix.height)
|
||||
elif matrix_aspect < image_aspect:
|
||||
# Letterbox vertically (horizontal bars top/bottom)
|
||||
scaled_size = (self.matrix.width,
|
||||
int(self.matrix.width / image_aspect + 0.5))
|
||||
else:
|
||||
# No letterbox, maybe just scale
|
||||
scaled_size = self.matrix_size
|
||||
position = ((self.matrix.width - scaled_size[0]) // 2,
|
||||
(self.matrix.height - scaled_size[1]) // 2)
|
||||
resize = (image.size != scaled_size)
|
||||
if scaled_size != self.matrix_size:
|
||||
back_image = Image.new("RGB", self.matrix_size)
|
||||
else:
|
||||
back_image = None
|
||||
|
||||
# Repeat until >= 10 seconds elapsed or 1 full pass through file
|
||||
while (time.time() - file_start_time) <= LOOP_TIME:
|
||||
# File playback is NOT cut off at 10 sec; all frames will
|
||||
# play as long as the file STARTED before the 10 sec cutoff.
|
||||
for frame in ImageSequence.Iterator(image):
|
||||
# Save frame duration, gets lost in the convert/resize
|
||||
next_duration = frame.info.get('duration', 100) / 1000.0
|
||||
if resize:
|
||||
# Frame must be converted to RGB and resized each time,
|
||||
# can't just do that operation once on the input image,
|
||||
# as the RGB conversion makes it lose its "GIF-ness."
|
||||
frame = frame.convert('RGB')
|
||||
frame = frame.resize(scaled_size, resample=FILTER)
|
||||
if back_image:
|
||||
back_image.paste(frame, position)
|
||||
self.double_buffer.SetImage(back_image)
|
||||
else:
|
||||
self.double_buffer.SetImage(frame)
|
||||
# Pause before showing new frame if prior frame delay
|
||||
# has not yet fully elapsed.
|
||||
frame_delay = (self.frame_duration -
|
||||
(time.time() - self.frame_start_time))
|
||||
if frame_delay > 0.0:
|
||||
time.sleep(frame_delay)
|
||||
self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer)
|
||||
self.frame_start_time = time.time()
|
||||
self.frame_duration = next_duration
|
||||
|
||||
def run(self):
|
||||
# Handle script-specific command line argument(s):
|
||||
if self.args.dir is not None:
|
||||
self.gif_path = self.args.dir
|
||||
|
||||
# Create offscreen buffer for graphics
|
||||
self.double_buffer = self.matrix.CreateFrameCanvas()
|
||||
|
||||
self.matrix_size = (self.matrix.width, self.matrix.height)
|
||||
|
||||
os.chdir(self.gif_path)
|
||||
while True:
|
||||
for filename in glob.glob("*.gif"):
|
||||
try:
|
||||
image = Image.open(filename)
|
||||
self.loop_gif(image)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
MY_APP = GIFplayer() # Instantiate class, calls __init__() above
|
||||
MY_APP.process() # SpectroBase startup, calls run() above
|
||||
2
life.py
2
life.py
|
|
@ -34,7 +34,7 @@ class Life(SpectroBase):
|
|||
# 'now' grid initially copies size/state from 'prior'...
|
||||
self.grid_now = deepcopy(self.grid_prior)
|
||||
# ...then set ~25% of pixels randomly (some may overlap, is OK):
|
||||
for count in range(self.matrix.width * self.matrix.height / 4):
|
||||
for count in range(self.matrix.width * self.matrix.height // 4):
|
||||
self.grid_now[randrange(self.matrix.height)][
|
||||
randrange(self.matrix.width)] = 1
|
||||
self.repetitions = 0 # Reset repetition counter
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ except ImportError:
|
|||
PROGRAMS = (
|
||||
("ipaddr.py", False),
|
||||
("bargraph.py", False),
|
||||
("life.py", False))
|
||||
("life.py", False),
|
||||
("gifplay.py", False))
|
||||
# Python version to use with any .py scripts in above list, in case
|
||||
# version 2 or 3 needs to be forced:
|
||||
PYTHON = "python"
|
||||
|
|
|
|||
Loading…
Reference in a new issue