Option added to show a slideshow of taken pictures when idle
This commit is contained in:
22
gui.py
22
gui.py
@@ -78,12 +78,12 @@ class GUI_PyGame:
|
|||||||
surface = pygame.transform.flip(surface, True, False)
|
surface = pygame.transform.flip(surface, True, False)
|
||||||
self.surface_list.append((surface, offset))
|
self.surface_list.append((surface, offset))
|
||||||
|
|
||||||
def show_message(self, msg, color=(245,245,245), bg=(0,0,0), transparency=True):
|
def show_message(self, msg, color=(0,0,0), bg=(230,230,230), transparency=True, outline=(245,245,245)):
|
||||||
# Choose font
|
# Choose font
|
||||||
font = pygame.font.Font(None, 144)
|
font = pygame.font.Font(None, 144)
|
||||||
# Wrap and render text
|
# Wrap and render text
|
||||||
wrapped_text, text_height = self.wrap_text(msg, font, self.size)
|
wrapped_text, text_height = self.wrap_text(msg, font, self.size)
|
||||||
rendered_text = self.render_text(wrapped_text, text_height, 1, 1, font, color, bg, transparency)
|
rendered_text = self.render_text(wrapped_text, text_height, 1, 1, font, color, bg, transparency, outline)
|
||||||
|
|
||||||
self.surface_list.append((rendered_text, (0,0)))
|
self.surface_list.append((rendered_text, (0,0)))
|
||||||
|
|
||||||
@@ -137,7 +137,7 @@ class GUI_PyGame:
|
|||||||
|
|
||||||
return final_lines, accumulated_height
|
return final_lines, accumulated_height
|
||||||
|
|
||||||
def render_text(self, text, text_height, valign, halign, font, color, bg, transparency):
|
def render_text(self, text, text_height, valign, halign, font, color, bg, transparency, outline):
|
||||||
# Determine vertical position
|
# Determine vertical position
|
||||||
if valign == 0: # top aligned
|
if valign == 0: # top aligned
|
||||||
voffset = 0
|
voffset = 0
|
||||||
@@ -155,16 +155,24 @@ class GUI_PyGame:
|
|||||||
# Blit one line after another
|
# Blit one line after another
|
||||||
accumulated_height = 0
|
accumulated_height = 0
|
||||||
for line in text:
|
for line in text:
|
||||||
tempsurface = font.render(line, 1, color)
|
maintext = font.render(line, 1, color)
|
||||||
|
shadow = font.render(line, 1, outline)
|
||||||
if halign == 0: # left aligned
|
if halign == 0: # left aligned
|
||||||
hoffset = 0
|
hoffset = 0
|
||||||
elif halign == 1: # centered
|
elif halign == 1: # centered
|
||||||
hoffset = (self.size[0] - tempsurface.get_width()) / 2
|
hoffset = (self.size[0] - maintext.get_width()) / 2
|
||||||
elif halign == 2: # right aligned
|
elif halign == 2: # right aligned
|
||||||
hoffset = rect.width - tempsurface.get_width()
|
hoffset = rect.width - maintext.get_width()
|
||||||
else:
|
else:
|
||||||
raise GuiException("Invalid halign argument: " + str(justification))
|
raise GuiException("Invalid halign argument: " + str(justification))
|
||||||
surface.blit(tempsurface, (hoffset, voffset + accumulated_height))
|
pos = (hoffset, voffset + accumulated_height)
|
||||||
|
# Outline
|
||||||
|
surface.blit(shadow, (pos[0]-1,pos[1]-1))
|
||||||
|
surface.blit(shadow, (pos[0]-1,pos[1]+1))
|
||||||
|
surface.blit(shadow, (pos[0]+1,pos[1]-1))
|
||||||
|
surface.blit(shadow, (pos[0]+1,pos[1]+1))
|
||||||
|
# Text
|
||||||
|
surface.blit(maintext, pos)
|
||||||
accumulated_height += font.size(line)[1]
|
accumulated_height += font.size(line)[1]
|
||||||
|
|
||||||
# Make background color transparent
|
# Make background color transparent
|
||||||
|
|||||||
@@ -10,8 +10,9 @@ from time import sleep, clock
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
from gui import GUI_PyGame as GuiModule
|
from gui import GUI_PyGame as GuiModule
|
||||||
#from camera import CameraException, Camera_cv as CameraModule
|
# from camera import CameraException, Camera_cv as CameraModule
|
||||||
from camera import CameraException, Camera_gPhoto as CameraModule
|
from camera import CameraException, Camera_gPhoto as CameraModule
|
||||||
|
from slideshow import Slideshow
|
||||||
from events import Rpi_GPIO as GPIO
|
from events import Rpi_GPIO as GPIO
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
@@ -42,9 +43,15 @@ gpio_lamp_channel = 4 # pin 7 in all Raspi-Versions
|
|||||||
# Waiting time in seconds for posing
|
# Waiting time in seconds for posing
|
||||||
pose_time = 5
|
pose_time = 5
|
||||||
|
|
||||||
# Display time for taken pictures
|
# Display time for assembled picture
|
||||||
display_time = 10
|
display_time = 10
|
||||||
|
|
||||||
|
# Show a slideshow of existing pictures when idle
|
||||||
|
idle_slideshow = True
|
||||||
|
|
||||||
|
# Display time of pictures in the slideshow
|
||||||
|
slideshow_display_time = 5
|
||||||
|
|
||||||
###############
|
###############
|
||||||
### Classes ###
|
### Classes ###
|
||||||
###############
|
###############
|
||||||
@@ -105,7 +112,7 @@ class Photobooth:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, display_size, picture_basename, picture_size, pose_time, display_time,
|
def __init__(self, display_size, picture_basename, picture_size, pose_time, display_time,
|
||||||
trigger_channel, shutdown_channel, lamp_channel):
|
trigger_channel, shutdown_channel, lamp_channel, idle_slideshow, slideshow_display_time):
|
||||||
self.display = GuiModule('Photobooth', display_size)
|
self.display = GuiModule('Photobooth', display_size)
|
||||||
self.pictures = PictureList(picture_basename)
|
self.pictures = PictureList(picture_basename)
|
||||||
self.camera = CameraModule(picture_size)
|
self.camera = CameraModule(picture_size)
|
||||||
@@ -118,6 +125,12 @@ class Photobooth:
|
|||||||
self.shutdown_channel = shutdown_channel
|
self.shutdown_channel = shutdown_channel
|
||||||
self.lamp_channel = lamp_channel
|
self.lamp_channel = lamp_channel
|
||||||
|
|
||||||
|
self.idle_slideshow = idle_slideshow
|
||||||
|
if self.idle_slideshow:
|
||||||
|
self.slideshow_display_time = slideshow_display_time
|
||||||
|
self.slideshow = Slideshow(display_size, display_time,
|
||||||
|
os.path.dirname(os.path.realpath(picture_basename)))
|
||||||
|
|
||||||
input_channels = [ trigger_channel, shutdown_channel ]
|
input_channels = [ trigger_channel, shutdown_channel ]
|
||||||
output_channels = [ lamp_channel ]
|
output_channels = [ lamp_channel ]
|
||||||
self.gpio = GPIO(self.handle_gpio, input_channels, output_channels)
|
self.gpio = GPIO(self.handle_gpio, input_channels, output_channels)
|
||||||
@@ -132,21 +145,38 @@ class Photobooth:
|
|||||||
self.gpio.teardown()
|
self.gpio.teardown()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
|
def _run_plain(self):
|
||||||
|
while True:
|
||||||
|
self.camera.set_idle()
|
||||||
|
|
||||||
|
# Display default message
|
||||||
|
self.display.clear()
|
||||||
|
self.display.show_message("Hit the button!")
|
||||||
|
self.display.apply()
|
||||||
|
|
||||||
|
# Wait for an event and handle it
|
||||||
|
event = self.display.wait_for_event()
|
||||||
|
self.handle_event(event)
|
||||||
|
|
||||||
|
def _run_slideshow(self):
|
||||||
|
while True:
|
||||||
|
self.camera.set_idle()
|
||||||
|
self.slideshow.display_next("Hit the button!")
|
||||||
|
tic = clock()
|
||||||
|
while clock() - tic < self.slideshow_display_time:
|
||||||
|
self.check_and_handle_events()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
# Enable lamp
|
# Enable lamp
|
||||||
self.gpio.set_output(self.lamp_channel, 1)
|
self.gpio.set_output(self.lamp_channel, 1)
|
||||||
|
|
||||||
while True:
|
# Select idle screen type
|
||||||
self.camera.set_idle()
|
if self.idle_slideshow:
|
||||||
# Display default message
|
self._run_slideshow()
|
||||||
self.display.clear()
|
else:
|
||||||
self.display.show_message("Hit the button!")
|
self._run_plain()
|
||||||
self.display.apply()
|
|
||||||
# Wait for an event and handle it
|
|
||||||
event = self.display.wait_for_event()
|
|
||||||
self.handle_event(event)
|
|
||||||
|
|
||||||
# Catch exceptions and display message
|
# Catch exceptions and display message
|
||||||
except CameraException as e:
|
except CameraException as e:
|
||||||
@@ -158,6 +188,12 @@ class Photobooth:
|
|||||||
print('SERIOUS ERROR: ' + repr(e))
|
print('SERIOUS ERROR: ' + repr(e))
|
||||||
self.handle_exception("SERIOUS ERROR!")
|
self.handle_exception("SERIOUS ERROR!")
|
||||||
|
|
||||||
|
def check_and_handle_events(self):
|
||||||
|
r, e = self.display.check_for_event()
|
||||||
|
while r:
|
||||||
|
self.handle_event(e)
|
||||||
|
r, e = self.display.check_for_event()
|
||||||
|
|
||||||
def handle_gpio(self, channel):
|
def handle_gpio(self, channel):
|
||||||
if channel in [ self.trigger_channel, self.shutdown_channel ]:
|
if channel in [ self.trigger_channel, self.shutdown_channel ]:
|
||||||
self.display.trigger_event(channel)
|
self.display.trigger_event(channel)
|
||||||
@@ -282,14 +318,13 @@ class Photobooth:
|
|||||||
|
|
||||||
def show_counter(self, seconds):
|
def show_counter(self, seconds):
|
||||||
if self.camera.has_preview():
|
if self.camera.has_preview():
|
||||||
tic, toc = clock(), 0
|
tic = clock()
|
||||||
while toc < self.pose_time:
|
while clock() - tic < seconds:
|
||||||
self.display.clear()
|
self.display.clear()
|
||||||
self.camera.take_preview("/tmp/photobooth_preview.jpg")
|
self.camera.take_preview("/tmp/photobooth_preview.jpg")
|
||||||
self.display.show_picture("/tmp/photobooth_preview.jpg", flip=True)
|
self.display.show_picture("/tmp/photobooth_preview.jpg", flip=True)
|
||||||
self.display.show_message(str(seconds - int(clock() - tic)))
|
self.display.show_message(str(seconds - int(clock() - tic)))
|
||||||
self.display.apply()
|
self.display.apply()
|
||||||
toc = clock() - tic
|
|
||||||
else:
|
else:
|
||||||
for i in range(seconds):
|
for i in range(seconds):
|
||||||
self.display.clear()
|
self.display.clear()
|
||||||
@@ -376,7 +411,8 @@ class Photobooth:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
photobooth = Photobooth(display_size, picture_basename, image_size, pose_time, display_time,
|
photobooth = Photobooth(display_size, picture_basename, image_size, pose_time, display_time,
|
||||||
gpio_trigger_channel, gpio_shutdown_channel, gpio_lamp_channel)
|
gpio_trigger_channel, gpio_shutdown_channel, gpio_lamp_channel,
|
||||||
|
idle_slideshow, slideshow_display_time)
|
||||||
photobooth.run()
|
photobooth.run()
|
||||||
photobooth.teardown()
|
photobooth.teardown()
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
41
slideshow.py
41
slideshow.py
@@ -40,6 +40,7 @@ class Slideshow:
|
|||||||
self.filelist = []
|
self.filelist = []
|
||||||
self.display = GuiModule("Slideshow", display_size)
|
self.display = GuiModule("Slideshow", display_size)
|
||||||
self.display_time = display_time
|
self.display_time = display_time
|
||||||
|
self.next = 0
|
||||||
|
|
||||||
def scan(self):
|
def scan(self):
|
||||||
filelist = []
|
filelist = []
|
||||||
@@ -57,6 +58,7 @@ class Slideshow:
|
|||||||
filelist.append(filename)
|
filelist.append(filename)
|
||||||
|
|
||||||
self.filelist = filelist
|
self.filelist = filelist
|
||||||
|
self.next = 0
|
||||||
|
|
||||||
def handle_event(self, event):
|
def handle_event(self, event):
|
||||||
if event.type == 0:
|
if event.type == 0:
|
||||||
@@ -69,23 +71,32 @@ class Slideshow:
|
|||||||
if key == ord('q'):
|
if key == ord('q'):
|
||||||
self.teardown()
|
self.teardown()
|
||||||
|
|
||||||
|
def display_next(self, text=""):
|
||||||
|
if self.next >= len(self.filelist):
|
||||||
|
self.scan()
|
||||||
|
if not self.filelist:
|
||||||
|
self.display.clear()
|
||||||
|
if text:
|
||||||
|
self.display.show_message(text)
|
||||||
|
else:
|
||||||
|
self.display.show_message("No pictures available!")
|
||||||
|
self.display.apply()
|
||||||
|
else:
|
||||||
|
filename = self.filelist[self.next]
|
||||||
|
self.next += 1
|
||||||
|
self.display.clear()
|
||||||
|
self.display.show_picture(filename)
|
||||||
|
if text:
|
||||||
|
self.display.show_message(text)
|
||||||
|
self.display.apply()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
while True:
|
while True:
|
||||||
self.scan()
|
self.display_next()
|
||||||
if len(self.filelist) == 0:
|
sleep(self.display_time)
|
||||||
self.display.clear()
|
r, e = self.display.check_for_event()
|
||||||
self.display.show_message("No pictures available!")
|
if r:
|
||||||
self.display.apply()
|
self.handle_event(e)
|
||||||
sleep(10)
|
|
||||||
else:
|
|
||||||
for filename in self.filelist:
|
|
||||||
self.display.clear()
|
|
||||||
self.display.show_picture(filename)
|
|
||||||
self.display.apply()
|
|
||||||
sleep(self.display_time)
|
|
||||||
r, e = self.display.check_for_event()
|
|
||||||
if r:
|
|
||||||
self.handle_event(e)
|
|
||||||
|
|
||||||
def teardown(self):
|
def teardown(self):
|
||||||
self.display.teardown()
|
self.display.teardown()
|
||||||
|
|||||||
Reference in New Issue
Block a user