def __init__(self, photobooth): self.menu_text = "Take continuous photos" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.total_pics = 17280 # 24 hours of a photo every 5 seconds self.capture_delay = 5 self.difference_threshold = 40
def __init__(self, photobooth): self.menu_text = "Create photo animation" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.gif_delay = 100 self.photo_width = 500 self.capture_delay = 2 self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler)
def __init__(self, photobooth): self.menu_text = "Take official profile photo (for Learn etc.)" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) # Set image definitions - width, height, dpi self.image_defs = [['learn', 150, 150, 300], ['pure', 160, 185, 300], ['eevec', 100, 150, 300], ['office365', 300, 300, 300]]
def __init__(self, photobooth): self.menu_text = "Take accompanied photo" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.chosen_accompaniment = 0 self.accompaniment_dir = self.filehandler.get_full_path( config.images_dir, 'accompany') self.accompany_button_overlay_image = self.filehandler.get_full_path( config.images_dir, 'accompany_button_overlay.png')
def __init__(self, photobooth): self.menu_text = "Take accompanied photo" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.chosen_accompaniment = 0 self.accompaniment_dir = self.filehandler.get_full_path(config.images_dir, 'accompany') self.accompany_button_overlay_image = self.filehandler.get_full_path(config.images_dir, 'accompany_button_overlay.png')
def __init__(self, photobooth): self.menu_text = "Take official profile photo (for Learn etc.)" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) # Set image definitions - width, height, dpi self.image_defs = [ ['learn', 150, 150, 300], ['pure', 160, 185, 300], ['eevec', 100, 150, 300], ['office365', 300, 300, 300] ]
class ContinuousPhotos(PhotoBoothFunction): 'Class to continuously take photos' reference_photo_image = None def __init__(self, photobooth): self.menu_text = "Take continuous photos" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.total_pics = 17280 # 24 hours of a photo every 5 seconds self.capture_delay = 5 self.difference_threshold = 40 def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" self.instructions = [ "Press Start and stand out of shot", "so a reference photo of background", "can be taken", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return # Set total_pics so we take our one background reference photo first self.set_total_pics(10000) self.take_photos() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(ContinuousPhotos, self).take_photos() ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare the user ######################## time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def manipulate_photo(self, filepath): # Use the first photo as a background reference photo if self.reference_photo_image is None: image_dir = self.filehandler.get_local_file_dir() # If reference_photo_image hasn't been assigned yet, then only one photo has been taken file_pattern = os.path.join(image_dir, self.photo_file_prefix + "*" + self.image_extension) self.reference_photo_image = Image.open(self.filehandler.get_sorted_file_list(file_pattern)[0]) # Take this opportunity to upload supporting files (HTML, etc.) self.upload_supporting_files() else: filepath_img = Image.open(filepath) # Compare the new photo to the background reference photo rms = self.photohandler.rms_difference(filepath_img, self.reference_photo_image) print "Difference to reference image: " + str(rms) if rms < self.difference_threshold: # It looks like this photo isn't very differnt to the background self.filehandler.delete_file(filepath) else: # It looks like this photo is very different from the background self.upload_photo(filepath) def process_photos(self): pass def upload_photos(self): pass # Create a thumbnail of the first image in the series def create_thumbnail(self): thumb_width = 200 file_list = self.filehandler.get_sorted_file_list(os.path.join(self.local_file_dir, '*' + self.image_extension)) img = self.photohandler.resize_image(file_list[0], thumb_width, thumb_width) img.save(os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension)) def upload_supporting_files(self): remote_upload_dir = time.strftime("%d-%b-%Y_C") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_defs = [ # Upload the HTML files to handle the continuous photos [os.path.join('html', 'individual', 'index-continuous.php'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], [os.path.join('html', 'individual', 'img-continuous.php'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Make sure the base .htaccess and index files are in place [os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True], [os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True], [os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True], # Make sure that all common files are in place [os.path.join('html', 'common', '*'), '', os.path.join(self.remote_file_dir, 'common'), 0, True], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None def upload_photo(self, filename): remote_upload_dir = time.strftime("%d-%b-%Y_C") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_suffix = time.strftime("%H-%M-%S") file_defs = [ # Upload the latest photo [filename, 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True] ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None
class AnimatedPhoto(PhotoBoothFunction): 'Class to take a series of photographs and combine them into an animated gif' def __init__(self, photobooth): self.menu_text = "Create photo animation" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.gif_delay = 100 self.photo_width = 500 self.capture_delay = 2 self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ total_pics_msg + " will be taken", "(red light will appear before each photo)", "The photos are then animated together", "Press the Start button to begin" ] # Outer loop: Instructions screen while True: choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": break while True: self.take_photos() # NOTE: If you change any part of this text display, mirror changes in erase print below text_rect_list = self.textprinter.print_text([["Processing. Please wait ...", 84, config.white_colour, "cb", 10]], 0, False) # Convert the images into an animated GIF (in a separate thread) gif_thread = threading.Thread(target=self.process_photos) gif_thread.start() # Now display the original images one after the other in separate thread, # to give the impression they are animated # (easier then trying to display the animated GIF in pygame?) display_thread_stop = threading.Event() display_thread = threading.Thread(target=self.photohandler.show_photos_animated, args=(self.image_extension, display_thread_stop)) display_thread.start() # Wait until the thread that's creating and uploading the GIF finishes gif_thread.join() # Overwrite the 'Processing' message in black to erase it screen_colour_fill(self.screen, config.black_colour, text_rect_list[0]) #self.textprinter.print_text([["Processing. Please wait ...", 84, config.black_colour, "cb", 10]], # 0, False) # Print the button label overlays self.imageprinter.print_images([[config.start_overlay_image_bk_black, 'cb', 0, 0]], False) self.imageprinter.print_images([[config.exit_side_overlay_image_bk_black, 'lb', 0, 0]], False) # Wait for the user to click Exit or Start choice = "" while True: choice = self.buttonhandler.wait_for_buttons('ls', True) if choice != 'screensaver': break # Now we can stop the thread that's animating the images on the screen display_thread_stop.set() display_thread.join() # If user pressed Exit button, return to Photo Animation Instruction screen if choice == 'l': break def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(AnimatedPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare the user ######################## time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def process_photos(self): self.combine_into_gif() self.create_thumbnail() self.upload_photos() # Create a thumbnail of the first image in the series def create_thumbnail(self): thumb_width = 200 file_list = self.filehandler.get_sorted_file_list(os.path.join(self.local_file_dir, '*' + self.image_extension)) img = self.photohandler.resize_image(file_list[0], thumb_width, thumb_width) img.save(os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension)) def upload_photos(self): remote_upload_dir = time.strftime("%d-%b-%Y_A") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_suffix = time.strftime("%H-%M-%S") file_defs = [ # Upload the animated GIF [os.path.join(self.local_upload_file_dir, '*' + self.animated_image_extension), 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload just the first of the photo files [os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension), 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload the HTML files to handle the animated photos [os.path.join('html', 'individual', 'index-animated.php'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], [os.path.join('html', 'individual', 'img-animated.php'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Make sure the base .htaccess and index files are in place [os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True], [os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True], [os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True], # Make sure that all common files are in place [os.path.join('html', 'common', '*'), '', os.path.join(self.remote_file_dir, 'common'), 0, True], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None def combine_into_gif(self): local_file_dir = self.filehandler.get_local_file_dir() print "Creating animated GIF ..." # Thanks to drumminhands graphicsmagick = ("gm convert -delay " + str(self.gif_delay) + " " + local_file_dir + "/*.jpg " + self.local_upload_file_dir + "/photobooth.gif") os.system(graphicsmagick) #make the .gif
class AccompaniedPhoto(PhotoBoothFunction): 'Class to take a photograph with a companion' def __init__(self, photobooth): self.menu_text = "Take accompanied photo" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.chosen_accompaniment = 0 self.accompaniment_dir = self.filehandler.get_full_path(config.images_dir, 'accompany') self.accompany_button_overlay_image = self.filehandler.get_full_path(config.images_dir, 'accompany_button_overlay.png') def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ "Press Left & Right to change companion", "Press Select button to choose companion", total_pics_msg + " will be taken", "(red light will appear before each photo)", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return self.take_photos() self.photohandler.show_photos_tiled(self.image_extension) time.sleep(2) choice = self.user_accept_photos() # See if user wants to accept photos if (choice == 'r'): self.process_photos() remote_upload_dir = self.upload_photos() if remote_upload_dir is None: self.display_upload_failed_message() else: remote_url_prefix = self.filehandler.get_remote_url_prefix() self.display_download_url(remote_url_prefix, remote_upload_dir) else: self.display_rejected_message() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(AccompaniedPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# # Collect together the PNG versions of all available accompaniment files file_pattern = self.filehandler.get_full_path(self.accompaniment_dir, "*.png") self.accompaniment_files = self.filehandler.get_sorted_file_list(file_pattern) ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - User make selection ######################## self.choose_accompaniment() time.sleep(self.prep_delay_long) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def manipulate_photo(self, filepath): # Superimpose the accompanying image onto the captured image # http://effbot.org/imagingbook/image.htm # super_image is RGBA, so use it both for image and mask if self.chosen_accompaniment > 1 and self.chosen_accompaniment < (len(self.accompaniment_files) + 2): curr_accompaniment_file = self.accompaniment_files[self.chosen_accompaniment - 2] curr_img = Image.open(filepath) super_img = Image.open(curr_accompaniment_file) curr_img.paste(super_img, None, super_img) curr_img.save(filepath) def upload_photos(self): self.textprinter.print_text([["Uploading photos ...", 124, config.black_colour, "cm", 0]], 0, True) remote_upload_dir = StringOperations().get_random_string(10) file_defs = [ # Upload the ZIP archive of photos [os.path.join(self.local_upload_file_dir, '*.zip'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload just the first of the photo files [os.path.join(self.local_file_dir, '*' + self.image_extension), 'photobooth_photo', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload the HTML file for this particular set of photos [os.path.join('html', 'individual', 'index-single.html'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Make sure the base .htaccess and index files are in place [os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True], [os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True], [os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True], # Make sure that all common files are in place [os.path.join('html', 'common', '*.css'), '', os.path.join(self.remote_file_dir, 'common'), 0, True], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None # Let the user select which image they want to be photographed with def choose_accompaniment(self): # Start with the first image (if there are any) self.chosen_accompaniment = 2 # Use the JPG versions of accompaniment files, which have black background file_pattern = self.filehandler.get_full_path(self.accompaniment_dir, "*.jpg") files = self.filehandler.get_sorted_file_list(file_pattern) # If there are no images, then chosen_accompaniment will be the blank screen if len(files) < 1: return 1 button_overlay = OverlayOnCamera(self.camera) button_overlay.camera_overlay(self.accompany_button_overlay_image) self.overlay_on_camera = OverlayOnCamera(self.camera) self.change_accompaniment(files) while True: choice = self.buttonhandler.wait_for_buttons('lsr', False) if choice == 'l': if self.chosen_accompaniment > 1: self.chosen_accompaniment -= 1 else: self.chosen_accompaniment = len(files) + 1 self.change_accompaniment(files) if choice == 'r': if self.chosen_accompaniment < (len(files) + 1): self.chosen_accompaniment += 1 else: self.chosen_accompaniment = 1 self.change_accompaniment(files) if choice == 's': self.buttonhandler.light_button_leds('lsr', False) break button_overlay.remove_camera_overlay() def change_accompaniment(self, files): self.camera.saturation = 0 # We leave a blank space for chosen_accompaniment == 1 accompanying_file_num = self.chosen_accompaniment - 2 # If chosen_accompaniment == 1, then we don't want any images overlaid if accompanying_file_num < 0 or accompanying_file_num > (len(files) - 1): self.overlay_on_camera.remove_camera_overlay() return curr_accompaniment_file = files[accompanying_file_num] self.overlay_on_camera.camera_overlay(curr_accompaniment_file) # See if an opacity value in the filename [within square brackets] filename = os.path.basename(curr_accompaniment_file) opacity = filename[filename.find("[")+1:filename.find("]")] if len(opacity) > 0: opacity = int(opacity) if opacity < -100: opacity = -100 if opacity > 100: opacity = 100 self.camera.saturation = opacity
class OfficialPhoto(PhotoBoothFunction): 'Class to take official portrait photographs' def __init__(self, photobooth): self.menu_text = "Take official profile photo (for Learn etc.)" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) # Set image definitions - width, height, dpi self.image_defs = [ ['learn', 150, 150, 300], ['pure', 160, 185, 300], ['eevec', 100, 150, 300], ['office365', 300, 300, 300] ] def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ "A template will appear on screen", "Following that, " + total_pics_msg + " will be taken", "(red light will appear before each photo)", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return self.take_photos() self.photohandler.show_photos_tiled(self.image_extension) time.sleep(2) choice = self.user_accept_photos() # See if user wants to accept photos if (choice == 'r'): self.process_photos() remote_upload_dir = self.upload_photos() if remote_upload_dir is None: self.display_upload_failed_message() else: remote_url_prefix = self.filehandler.get_remote_url_prefix() self.display_download_url(remote_url_prefix, remote_upload_dir) else: self.display_rejected_message() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(OfficialPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# # Make the image square, using the photo_width pixel_width = self.photo_width pixel_height = self.photo_width self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare user ################################ self.overlay_on_camera = OverlayOnCamera(self.camera) # Apply overlay images & messages to prepare the user self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) self.overlay_on_camera.camera_overlay(config.face_target_fit_face_overlay_image) time.sleep(self.prep_delay_long) self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) self.overlay_on_camera.camera_overlay(config.face_target_smile_overlay_image) time.sleep(self.prep_delay_long) self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def upload_photos(self): self.textprinter.print_text([["Uploading photos ...", 124, config.black_colour, "cm", 0]], 0, True) remote_upload_dir = StringOperations().get_random_string(10) file_defs = [ # Upload the ZIP archive of photos [os.path.join(self.local_upload_file_dir, '*.zip'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload just the first of the photo files [os.path.join(self.local_file_dir, '*' + self.image_extension), 'photobooth_photo', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Upload the HTML file for this particular set of photos [os.path.join('html', 'individual', 'index-single.html'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True], # Make sure the base .htaccess and index files are in place [os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True], [os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True], [os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True], # Make sure that all common files are in place [os.path.join('html', 'common', '*.css'), '', os.path.join(self.remote_file_dir, 'common'), 0, True], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None
class ContinuousPhotos(PhotoBoothFunction): 'Class to continuously take photos' reference_photo_image = None def __init__(self, photobooth): self.menu_text = "Take continuous photos" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.total_pics = 17280 # 24 hours of a photo every 5 seconds self.capture_delay = 5 self.difference_threshold = 40 def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" self.instructions = [ "Press Start and stand out of shot", "so a reference photo of background", "can be taken", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return # Set total_pics so we take our one background reference photo first self.set_total_pics(10000) self.take_photos() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(ContinuousPhotos, self).take_photos() ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare the user ######################## time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def manipulate_photo(self, filepath): # Use the first photo as a background reference photo if self.reference_photo_image is None: image_dir = self.filehandler.get_local_file_dir() # If reference_photo_image hasn't been assigned yet, then only one photo has been taken file_pattern = os.path.join( image_dir, self.photo_file_prefix + "*" + self.image_extension) self.reference_photo_image = Image.open( self.filehandler.get_sorted_file_list(file_pattern)[0]) # Take this opportunity to upload supporting files (HTML, etc.) self.upload_supporting_files() else: filepath_img = Image.open(filepath) # Compare the new photo to the background reference photo rms = self.photohandler.rms_difference(filepath_img, self.reference_photo_image) print "Difference to reference image: " + str(rms) if rms < self.difference_threshold: # It looks like this photo isn't very differnt to the background self.filehandler.delete_file(filepath) else: # It looks like this photo is very different from the background self.upload_photo(filepath) def process_photos(self): pass def upload_photos(self): pass # Create a thumbnail of the first image in the series def create_thumbnail(self): thumb_width = 200 file_list = self.filehandler.get_sorted_file_list( os.path.join(self.local_file_dir, '*' + self.image_extension)) img = self.photohandler.resize_image(file_list[0], thumb_width, thumb_width) img.save( os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension)) def upload_supporting_files(self): remote_upload_dir = time.strftime("%d-%b-%Y_C") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_defs = [ # Upload the HTML files to handle the continuous photos [ os.path.join('html', 'individual', 'index-continuous.php'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], [ os.path.join('html', 'individual', 'img-continuous.php'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Make sure the base .htaccess and index files are in place [ os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True ], # Make sure that all common files are in place [ os.path.join('html', 'common', '*'), '', os.path.join(self.remote_file_dir, 'common'), 0, True ], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None def upload_photo(self, filename): remote_upload_dir = time.strftime("%d-%b-%Y_C") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_suffix = time.strftime("%H-%M-%S") file_defs = [ # Upload the latest photo [ filename, 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ] ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None
class AnimatedPhoto(PhotoBoothFunction): 'Class to take a series of photographs and combine them into an animated gif' def __init__(self, photobooth): self.menu_text = "Create photo animation" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.gif_delay = 100 self.photo_width = 500 self.capture_delay = 2 self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ total_pics_msg + " will be taken", "(red light will appear before each photo)", "The photos are then animated together", "Press the Start button to begin" ] # Outer loop: Instructions screen while True: choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": break while True: self.take_photos() # NOTE: If you change any part of this text display, mirror changes in erase print below text_rect_list = self.textprinter.print_text([[ "Processing. Please wait ...", 84, config.white_colour, "cb", 10 ]], 0, False) # Convert the images into an animated GIF (in a separate thread) gif_thread = threading.Thread(target=self.process_photos) gif_thread.start() # Now display the original images one after the other in separate thread, # to give the impression they are animated # (easier then trying to display the animated GIF in pygame?) display_thread_stop = threading.Event() display_thread = threading.Thread( target=self.photohandler.show_photos_animated, args=(self.image_extension, display_thread_stop)) display_thread.start() # Wait until the thread that's creating and uploading the GIF finishes gif_thread.join() # Overwrite the 'Processing' message in black to erase it screen_colour_fill(self.screen, config.black_colour, text_rect_list[0]) #self.textprinter.print_text([["Processing. Please wait ...", 84, config.black_colour, "cb", 10]], # 0, False) # Print the button label overlays self.imageprinter.print_images( [[config.start_overlay_image_bk_black, 'cb', 0, 0]], False) self.imageprinter.print_images( [[config.exit_side_overlay_image_bk_black, 'lb', 0, 0]], False) # Wait for the user to click Exit or Start choice = "" while True: choice = self.buttonhandler.wait_for_buttons('ls', True) if choice != 'screensaver': break # Now we can stop the thread that's animating the images on the screen display_thread_stop.set() display_thread.join() # If user pressed Exit button, return to Photo Animation Instruction screen if choice == 'l': break def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(AnimatedPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare the user ######################## time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def process_photos(self): self.combine_into_gif() self.create_thumbnail() self.upload_photos() # Create a thumbnail of the first image in the series def create_thumbnail(self): thumb_width = 200 file_list = self.filehandler.get_sorted_file_list( os.path.join(self.local_file_dir, '*' + self.image_extension)) img = self.photohandler.resize_image(file_list[0], thumb_width, thumb_width) img.save( os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension)) def upload_photos(self): remote_upload_dir = time.strftime("%d-%b-%Y_A") if self.booth_id is not "": remote_upload_dir = self.booth_id + "_" + remote_upload_dir file_suffix = time.strftime("%H-%M-%S") file_defs = [ # Upload the animated GIF [ os.path.join(self.local_upload_file_dir, '*' + self.animated_image_extension), 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload just the first of the photo files [ os.path.join(self.local_file_dir, 'photobooth_thumb' + self.image_extension), 'photobooth_photo_' + file_suffix, os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload the HTML files to handle the animated photos [ os.path.join('html', 'individual', 'index-animated.php'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], [ os.path.join('html', 'individual', 'img-animated.php'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Make sure the base .htaccess and index files are in place [ os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True ], # Make sure that all common files are in place [ os.path.join('html', 'common', '*'), '', os.path.join(self.remote_file_dir, 'common'), 0, True ], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None def combine_into_gif(self): local_file_dir = self.filehandler.get_local_file_dir() print "Creating animated GIF ..." # Thanks to drumminhands graphicsmagick = ("gm convert -delay " + str(self.gif_delay) + " " + local_file_dir + "/*.jpg " + self.local_upload_file_dir + "/photobooth.gif") os.system(graphicsmagick) #make the .gif
class AccompaniedPhoto(PhotoBoothFunction): 'Class to take a photograph with a companion' def __init__(self, photobooth): self.menu_text = "Take accompanied photo" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) self.chosen_accompaniment = 0 self.accompaniment_dir = self.filehandler.get_full_path( config.images_dir, 'accompany') self.accompany_button_overlay_image = self.filehandler.get_full_path( config.images_dir, 'accompany_button_overlay.png') def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ "Press Left & Right to change companion", "Press Select button to choose companion", total_pics_msg + " will be taken", "(red light will appear before each photo)", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return self.take_photos() self.photohandler.show_photos_tiled(self.image_extension) time.sleep(2) choice = self.user_accept_photos() # See if user wants to accept photos if (choice == 'r'): self.process_photos() remote_upload_dir = self.upload_photos() if remote_upload_dir is None: self.display_upload_failed_message() else: remote_url_prefix = self.filehandler.get_remote_url_prefix() self.display_download_url(remote_url_prefix, remote_upload_dir) else: self.display_rejected_message() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(AccompaniedPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# # Collect together the PNG versions of all available accompaniment files file_pattern = self.filehandler.get_full_path(self.accompaniment_dir, "*.png") self.accompaniment_files = self.filehandler.get_sorted_file_list( file_pattern) ################################# Step 2 - Setup camera ################################# pixel_width = self.photo_width pixel_height = self.photohandler.get_aspect_ratio_height(pixel_width) self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - User make selection ######################## self.choose_accompaniment() time.sleep(self.prep_delay_long) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def manipulate_photo(self, filepath): # Superimpose the accompanying image onto the captured image # http://effbot.org/imagingbook/image.htm # super_image is RGBA, so use it both for image and mask if self.chosen_accompaniment > 1 and self.chosen_accompaniment < ( len(self.accompaniment_files) + 2): curr_accompaniment_file = self.accompaniment_files[ self.chosen_accompaniment - 2] curr_img = Image.open(filepath) super_img = Image.open(curr_accompaniment_file) curr_img.paste(super_img, None, super_img) curr_img.save(filepath) def upload_photos(self): self.textprinter.print_text( [["Uploading photos ...", 124, config.black_colour, "cm", 0]], 0, True) remote_upload_dir = StringOperations().get_random_string(10) file_defs = [ # Upload the ZIP archive of photos [ os.path.join(self.local_upload_file_dir, '*.zip'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload just the first of the photo files [ os.path.join(self.local_file_dir, '*' + self.image_extension), 'photobooth_photo', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload the HTML file for this particular set of photos [ os.path.join('html', 'individual', 'index-single.html'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Make sure the base .htaccess and index files are in place [ os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True ], # Make sure that all common files are in place [ os.path.join('html', 'common', '*.css'), '', os.path.join(self.remote_file_dir, 'common'), 0, True ], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None # Let the user select which image they want to be photographed with def choose_accompaniment(self): # Start with the first image (if there are any) self.chosen_accompaniment = 2 # Use the JPG versions of accompaniment files, which have black background file_pattern = self.filehandler.get_full_path(self.accompaniment_dir, "*.jpg") files = self.filehandler.get_sorted_file_list(file_pattern) # If there are no images, then chosen_accompaniment will be the blank screen if len(files) < 1: return 1 button_overlay = OverlayOnCamera(self.camera) button_overlay.camera_overlay(self.accompany_button_overlay_image) self.overlay_on_camera = OverlayOnCamera(self.camera) self.change_accompaniment(files) while True: choice = self.buttonhandler.wait_for_buttons('lsr', False) if choice == 'l': if self.chosen_accompaniment > 1: self.chosen_accompaniment -= 1 else: self.chosen_accompaniment = len(files) + 1 self.change_accompaniment(files) if choice == 'r': if self.chosen_accompaniment < (len(files) + 1): self.chosen_accompaniment += 1 else: self.chosen_accompaniment = 1 self.change_accompaniment(files) if choice == 's': self.buttonhandler.light_button_leds('lsr', False) break button_overlay.remove_camera_overlay() def change_accompaniment(self, files): self.camera.saturation = 0 # We leave a blank space for chosen_accompaniment == 1 accompanying_file_num = self.chosen_accompaniment - 2 # If chosen_accompaniment == 1, then we don't want any images overlaid if accompanying_file_num < 0 or accompanying_file_num > (len(files) - 1): self.overlay_on_camera.remove_camera_overlay() return curr_accompaniment_file = files[accompanying_file_num] self.overlay_on_camera.camera_overlay(curr_accompaniment_file) # See if an opacity value in the filename [within square brackets] filename = os.path.basename(curr_accompaniment_file) opacity = filename[filename.find("[") + 1:filename.find("]")] if len(opacity) > 0: opacity = int(opacity) if opacity < -100: opacity = -100 if opacity > 100: opacity = 100 self.camera.saturation = opacity
class OfficialPhoto(PhotoBoothFunction): 'Class to take official portrait photographs' def __init__(self, photobooth): self.menu_text = "Take official profile photo (for Learn etc.)" self.booth_id = photobooth.get_booth_id() self.screen = photobooth.get_pygame_screen() self.filehandler = photobooth.get_file_handler() self.buttonhandler = photobooth.get_button_handler() self.local_file_dir = self.filehandler.get_local_file_dir() self.local_upload_file_dir = self.filehandler.get_upload_file_dir() self.remote_file_dir = self.filehandler.get_remote_file_dir() self.textprinter = TextPrinter(self.screen) self.imageprinter = ImagePrinter(self.screen) self.photohandler = PhotoHandler(self.screen, self.filehandler) # Set image definitions - width, height, dpi self.image_defs = [['learn', 150, 150, 300], ['pure', 160, 185, 300], ['eevec', 100, 150, 300], ['office365', 300, 300, 300]] def start(self, total_pics=PhotoBoothFunction.total_pics): # Take and display photos self.total_pics = total_pics # Display the instructions for this photobooth function total_pics_msg = str(self.total_pics) + " photo" if self.total_pics > 1: total_pics_msg += "s" self.instructions = [ "A template will appear on screen", "Following that, " + total_pics_msg + " will be taken", "(red light will appear before each photo)", "Press the Start button to begin" ] choice = self.display_instructions() # If the user selected Exit, bail out if choice == "l": return self.take_photos() self.photohandler.show_photos_tiled(self.image_extension) time.sleep(2) choice = self.user_accept_photos() # See if user wants to accept photos if (choice == 'r'): self.process_photos() remote_upload_dir = self.upload_photos() if remote_upload_dir is None: self.display_upload_failed_message() else: remote_url_prefix = self.filehandler.get_remote_url_prefix() self.display_download_url(remote_url_prefix, remote_upload_dir) else: self.display_rejected_message() def take_photos(self): ################################# Step 1 - Initial Preparation ########################## super(OfficialPhoto, self).take_photos() ################################# Step 2 - Setup camera ################################# # Make the image square, using the photo_width pixel_width = self.photo_width pixel_height = self.photo_width self.camera.resolution = (pixel_width, pixel_height) ################################# Step 3 - Start camera preview ######################## screen_colour_fill(self.screen, config.black_colour) self.camera.start_preview() ################################# Step 4 - Prepare user ################################ self.overlay_on_camera = OverlayOnCamera(self.camera) # Apply overlay images & messages to prepare the user self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) self.overlay_on_camera.camera_overlay( config.face_target_fit_face_overlay_image) time.sleep(self.prep_delay_long) self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) self.overlay_on_camera.camera_overlay( config.face_target_smile_overlay_image) time.sleep(self.prep_delay_long) self.overlay_on_camera.camera_overlay(config.face_target_overlay_image) time.sleep(self.prep_delay_short) ################################# Step 5 - Take Photos ################################ self.take_photos_and_close_camera(self.capture_delay) def upload_photos(self): self.textprinter.print_text( [["Uploading photos ...", 124, config.black_colour, "cm", 0]], 0, True) remote_upload_dir = StringOperations().get_random_string(10) file_defs = [ # Upload the ZIP archive of photos [ os.path.join(self.local_upload_file_dir, '*.zip'), '', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload just the first of the photo files [ os.path.join(self.local_file_dir, '*' + self.image_extension), 'photobooth_photo', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Upload the HTML file for this particular set of photos [ os.path.join('html', 'individual', 'index-single.html'), 'index', os.path.join(self.remote_file_dir, remote_upload_dir), 1, True ], # Make sure the base .htaccess and index files are in place [ os.path.join('html', 'index.php'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', 'redirect.html'), '', self.remote_file_dir, 1, True ], [ os.path.join('html', '.htaccess'), '', self.remote_file_dir, 1, True ], # Make sure that all common files are in place [ os.path.join('html', 'common', '*.css'), '', os.path.join(self.remote_file_dir, 'common'), 0, True ], ] success = self.upload_photos_using_defs(file_defs) if success: return remote_upload_dir else: return None