diff --git a/camera.py b/camera.py index ed54ac3..17758bc 100644 --- a/camera.py +++ b/camera.py @@ -9,17 +9,17 @@ try: except ImportError: cv_enabled = False - class CameraException(Exception): """Custom exception class to handle camera class errors""" pass + class Camera_cv: - def __init__(self): + def __init__(self, picture_size): if cv_enabled: self.cap = cv.VideoCapture(0) - self.cap.set(3, 640) - self.cap.set(4, 480) + self.cap.set(3, picture_size[0]) + self.cap.set(4, picture_size[1]) def take_picture(self, filename="/tmp/picture.jpg"): if cv_enabled: @@ -27,13 +27,14 @@ class Camera_cv: cv.imwrite(filename, frame) return filename else: - return "/dev/null" + raise CameraException("OpenCV not available!") class Camera_gPhoto: """Camera class providing functionality to take pictures using gPhoto 2""" - # def __init__(self): + def __init__(self, picture_size): + self.picture_size = picture_size # Print the abilities of the connected camera # print(self.call_gphoto("-a", "/dev/null")) diff --git a/gui.py b/gui.py index 3ee45f8..b976e88 100644 --- a/gui.py +++ b/gui.py @@ -6,6 +6,8 @@ # - incorporate render_textrect # - restructure mainloop +from __future__ import division + import pygame try: @@ -142,8 +144,11 @@ class GUI_PyGame: def clear(self, color=(0,0,0)): self.screen.fill(color) + self.surface_list = [] def apply(self): + for surface in self.surface_list: + self.screen.blit(surface[0], surface[1]) pygame.display.update() def get_size(self): @@ -167,16 +172,21 @@ class GUI_PyGame: offset = tuple(a+int((b-c)/2) for a,b,c in zip(offset, size, new_size)) # Apply scaling and display picture image = pygame.transform.scale(image, new_size).convert() - self.screen.blit(image, offset) + # Create surface and blit the image to it + surface = pygame.Surface(new_size) + surface.blit(image, (0,0)) + self.surface_list.append((surface, offset)) - def show_message(self, msg, color=(245,245,245), bg=(0,0,0)): + def show_message(self, msg, color=(245,245,245), bg=(0,0,0), transparency=True): # Choose font font = pygame.font.Font(None, 144) # Create rectangle for text rect = pygame.Rect((0, 0, self.size[0], self.size[1])) # Render text text = render_textrect(msg, font, rect, color, bg, 1, 1) - self.screen.blit(text, rect.topleft) + if transparency: + text.set_colorkey(bg) + self.surface_list.append((text, rect.topleft)) def wait_for_event(self): # Repeat until a relevant event happened diff --git a/photobooth.py b/photobooth.py index bf9a06f..7a2f764 100755 --- a/photobooth.py +++ b/photobooth.py @@ -1,21 +1,16 @@ #!/usr/bin/env python # Created by br@re-web.eu, 2015 -from __future__ import division - import os from datetime import datetime from glob import glob from sys import exit -from time import sleep +from time import sleep, clock from PIL import Image from gui import GUI_PyGame as GuiModule - -from camera import Camera_gPhoto as CameraModule -from camera import CameraException - +from camera import CameraException, Camera_gPhoto as CameraModule from events import Rpi_GPIO as GPIO ##################### @@ -90,7 +85,7 @@ class Photobooth: trigger_channel, shutdown_channel, lamp_channel): self.display = GuiModule('Photobooth', display_size) self.pictures = PictureList(picture_basename) - self.camera = CameraModule() + self.camera = CameraModule(picture_size) self.pic_size = picture_size self.pose_time = pose_time @@ -105,6 +100,10 @@ class Photobooth: self.gpio = GPIO(self.handle_gpio, input_channels, output_channels) def teardown(self): + self.display.clear() + self.display.show_message("Shutting down...") + self.display.apply() + sleep(1) self.display.teardown() self.gpio.teardown() exit(0) @@ -172,7 +171,7 @@ class Photobooth: sleep(3) - def assemble_pictures(self, input_filenames, output_filename): + def assemble_pictures(self, input_filenames): """Assembles four pictures into a 2x2 grid""" # Thumbnail size of pictures @@ -191,7 +190,9 @@ class Photobooth: output_image.paste(img, offset) # Save resized image + output_filename = self.pictures.get_next() output_image.save(output_filename, "JPEG") + return output_filename def take_picture(self): """Implements the picture taking routine""" @@ -223,7 +224,11 @@ class Photobooth: # Take pictures filenames = [i for i in range(4)] for x in range(4): + tic = clock() filenames[x] = self.camera.take_picture("/tmp/photobooth_%02d.jpg" % x) + toc = clock() - tic + if toc < 1.0: + sleep(1.0 - toc) # Show 'Wait' self.display.clear() @@ -231,8 +236,7 @@ class Photobooth: self.display.apply() # Assemble them - outfile = self.pictures.get_next() - self.assemble_pictures(filenames, outfile) + outfile = self.assemble_pictures(filenames) # Show pictures for 10 seconds self.display.clear() @@ -254,7 +258,8 @@ def main(): photobooth = Photobooth(picture_basename, image_size, pose_time, display_time, gpio_trigger_channel, gpio_shutdown_channel, gpio_lamp_channel) photobooth.run() - return photobooth.teardown() + photobooth.teardown() + return 0 if __name__ == "__main__": exit(main()) \ No newline at end of file