Article Outline
Python pil example 'Jppi-0'
Functions in program:
def main(threadName, *args):
def pulse(threadName, *args):
def UpdateDisplay():
Modules used in program:
import cups
import ImageDraw
import PIL.Image
import os
import time
import pygame
import picamera
import RPi.GPIO as gpio
python Jppi-0
Python pil example: Jppi-0
######################################################################
# #
# MATT CAM #
# Version : 1.1 #
# #
# Description : #
# Raspberry PI Photobooth Software #
# Author : #
# Matt Inglis #
# #
######################################################################
#IMPORTS
import RPi.GPIO as gpio
import picamera
import pygame
import time
import os
import PIL.Image
import ImageDraw
import cups
from threading import Thread
from pygame.locals import *
from time import sleep
from PIL import Image
#initialise global variables
closeme = True #Loop Control Variable
timepulse = 999 #Pulse Rate of LED
LEDon = False #LED Flashing Control
gpio.setmode(gpio.BCM) #Set GPIO to BCM Layout
Numeral = "" #Numeral is the number display
Message = "" #Message is a fullscreen message
SmallMessage = "" #SmallMessage is a lower banner message
TotalImageCount = 1 #Counter for Display and to monitor paper usage
PhotosPerCart = 16 #Selphy takes 16 sheets per tray
#initialise pygame
pygame.mixer.pre_init(44100, -16, 1, 1024*3) #PreInit Music, plays faster
pygame.init() #Initialise pygame
screen = pygame.display.set_mode((800,480),pygame.FULLSCREEN) #Full screen 640x480
background = pygame.Surface(screen.get_size()) #Create the background object
background = background.convert() #Convert it to a background
#UpdateDisplay - Thread to update the display, neat generic procedure
def UpdateDisplay():
#init global variables from main thread
global Numeral
global Message
global SmallMessage
global TotalImageCount
global screen
global background
global pygame
SmallText = "Matt Cam" #Default Small Message Text
if(TotalImageCount >= (PhotosPerCart - 2)): #Low Paper Warning at 2 images less
SmallText = "Paper Running Low!..."
if(TotalImageCount >= PhotosPerCart): #Paper out warning when over Photos per cart
SmallMessage = "Paper Out!..."
TotalImageCount = 0
background.fill(pygame.Color("black")) #Black background
smallfont = pygame.font.Font(None, 50) #Small font for banner message
SmallText = smallfont.render(SmallText,1, (255,0,0))
background.blit(SmallText,(10,445)) #Write the small text
SmallText = smallfont.render('TotalImageCount'+"/"+'PhotosPerCart',1, (255,0,0))
background.blit(SmallText,(710,445)) #Write the image counter
if(Message != ""): #If the big message exits write it
font = pygame.font.Font(None, 180)
text = font.render(Message, 1, (255,0,0))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
textpos.centery = background.get_rect().centery
background.blit(text, textpos)
elif(Numeral != ""): # Else if the number exists display it
font = pygame.font.Font(None, 800)
text = font.render(Numeral, 1, (255,0,0))
textpos = text.get_rect()
textpos.centerx = background.get_rect().centerx
textpos.centery = background.get_rect().centery
background.blit(text, textpos)
screen.blit(background, (0,0))
pygame.draw.rect(screen,pygame.Color("red"),(10,10,770,430),2) #Draw the red outer box
pygame.display.flip()
return
#Pulse Thread - Used to pulse the LED without slowing down the rest
def pulse(threadName, *args):
#gpio.setmode(gpio.BCM)
global gpio
gpio.setup(17, gpio.OUT)
#print(timepulse)
while closeme:
#global LEDon
#print(LEDon)
if timepulse == 999:
gpio.output(17, True)
LEDon = True
else:
if LEDon:
gpio.output(17, False)
time.sleep(timepulse)
LEDon = False
else:
gpio.output(17, False)
time.sleep(timepulse)
LEDon = True
#Main Thread
def main(threadName, *args):
#Setup Variables
gpio.setup(24, gpio.IN) #Button on Pin 24 Reprints last image
gpio.setup(22, gpio.IN) #Button on Pin 22 is the shutter
global closeme
global timepulse
global TotalImageCount
global Numeral
global SmallMessage
global Message
Message = "Loading..."
UpdateDisplay()
time.sleep(5) #5 Second delay to allow USB to mount
#Initialise the camera object
camera = picamera.PiCamera()
#Transparency allows pigame to shine through
camera.preview_alpha = 120
camera.vflip = False
camera.hflip = True
camera.rotation = 90
camera.brightness = 45
camera.exposure_compensation = 6
camera.contrast = 8
camera.resolution = (1280,720)
#Start the preview
camera.start_preview()
Message = "USB Check..."
UpdateDisplay()
#Following is a check to see there is a USB mounted if not it loops with a USB message
usbcheck = False
rootdir = '/media/'
while not usbcheck:
dirs = os.listdir(rootdir)
for file in dirs:
folder = os.path.join(rootdir,file)
if not file == 'SETTINGS' and os.path.isdir(folder):
usbcheck = True
imagedrive = os.path.join(rootdir,file)
imagefolder = os.path.join(imagedrive,'PhotoBooth')
#If a photobooth folder on the usb doesn't exist create it
if not os.path.isdir(imagefolder):
os.makedirs(imagefolder)
Message = "Initialise"
UpdateDisplay()
#Procedure checks if a numerical folder exists, if it does pick the next number
#each start gets a new folder i.e. /photobooth/1/ etc
notfound = True
folderno = 1
while notfound:
tmppath = os.path.join(imagefolder,'folderno')
if not os.path.isdir(tmppath):
os.makedirs(tmppath)
imagefolder = tmppath
notfound = False
else:
folderno = folderno + 1
imagecounter = 0
Message = ""
UpdateDisplay()
#Main Loop
while closeme:
try:
for event in pygame.event.get():
if event.type == pygame.QUIT:
closeme = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
closeme = False
except KeyboardInterrupt:
closeme = False
#input_value is the shutter
input_value = gpio.input(22)
#input_value2 is photo reprint
input_value2 = gpio.input(24)
UpdateDisplay()
#Load a beep music file
pygame.mixer.music.load('/home/pi/Desktop/Beep.mp3')
#Reprint(Button has been pressed)
if input_value2==False:
#If the temp image exists send it to the printer
if os.path.isfile('/home/pi/Desktop/tempprint.jpg'):
#Open a connection to cups
conn = cups.Connection()
#get a list of printers
printers = conn.getPrinters()
#select printer 0
printer_name = printers.keys()[0]
Message = "Re-Print..."
UpdateDisplay()
#print(the buffer file)
printqueuelength = len(conn.getJobs())
if printqueuelength > 1:
Message = "PRINT ERROR"
conn.enablePrinter(printer_name)
UpdateDisplay()
elif printqueuelength == 1:
SmallMessage = "Print Queue Full!"
UpdateDisplay()
conn.enablePrinter(printer_name)
conn.printFile(printer_name,'/home/pi/Desktop/tempprint.jpg',"PhotoBooth",{})
time.sleep(20)
Message = ""
UpdateDisplay()
#input_value is the shutter release
if input_value == False:
subimagecounter = 0
#Increment the image number
imagecounter = imagecounter + 1
#play the beep
pygame.mixer.music.play(0)
#Display the countdown number
Numeral = "5"
UpdateDisplay()
#Flash the light at half second intervals
timepulse = 0.5
# 1 second between beeps
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "4"
UpdateDisplay()
timepulse = 0.4
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "3"
UpdateDisplay()
timepulse = 0.3
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "2"
UpdateDisplay()
timepulse = 0.2
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "1"
UpdateDisplay()
timepulse = 0.1
time.sleep(1)
#Camera shutter sound
pygame.mixer.music.load('/home/pi/Desktop/camera.mp3')
pygame.mixer.music.play(0)
Numeral = ""
Message = "Smile!"
UpdateDisplay()
#increment the subimage
subimagecounter = subimagecounter + 1
#create the filename
filename = 'image'
filename += 'imagecounter'
filename += '_'
filename += 'subimagecounter'
filename += '.jpg'
#capture the image
camera.capture(os.path.join(imagefolder,filename))
#create an image object
im = PIL.Image.open(os.path.join(imagefolder,filename)).transpose(Image.FLIP_LEFT_RIGHT)
pygame.mixer.music.load('/home/pi/Desktop/Beep.mp3')
Message = "Get Ready"
UpdateDisplay()
timepulse = 999
time.sleep(3)
pygame.mixer.music.play(0)
Message = ""
Numeral = "5"
UpdateDisplay()
timepulse = 0.5
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "4"
UpdateDisplay()
timepulse = 0.4
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "3"
UpdateDisplay()
timepulse = 0.3
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "2"
UpdateDisplay()
timepulse = 0.2
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "1"
UpdateDisplay()
timepulse = 0.1
time.sleep(1)
pygame.mixer.music.load('/home/pi/Desktop/camera.mp3')
pygame.mixer.music.play(0)
Numeral = ""
Message = "Smile!"
UpdateDisplay()
subimagecounter = subimagecounter + 1
filename = 'image'
filename += 'imagecounter'
filename += '_'
filename += 'subimagecounter'
filename += '.jpg'
camera.capture(os.path.join(imagefolder,filename))
im2 = PIL.Image.open(os.path.join(imagefolder,filename)).transpose(Image.FLIP_LEFT_RIGHT)
pygame.mixer.music.load('/home/pi/Desktop/Beep.mp3')
Message = "Another One"
UpdateDisplay()
timepulse = 999
time.sleep(3)
pygame.mixer.music.play(0)
Numeral = "5"
Message = ""
UpdateDisplay()
timepulse = 0.5
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "4"
UpdateDisplay()
timepulse = 0.4
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "3"
UpdateDisplay()
timepulse = 0.3
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "2"
UpdateDisplay()
timepulse = 0.2
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "1"
UpdateDisplay()
timepulse = 0.1
time.sleep(1)
pygame.mixer.music.load('/home/pi/Desktop/camera.mp3')
pygame.mixer.music.play(0)
Numeral = ""
Message = "Smile!"
UpdateDisplay()
subimagecounter = subimagecounter + 1
filename = 'image'
filename += 'imagecounter'
filename += '_'
filename += 'subimagecounter'
filename += '.jpg'
camera.capture(os.path.join(imagefolder,filename))
im3 = PIL.Image.open(os.path.join(imagefolder,filename)).transpose(Image.FLIP_LEFT_RIGHT)
pygame.mixer.music.load('/home/pi/Desktop/Beep.mp3')
Message = "Final One!"
UpdateDisplay()
timepulse = 999
time.sleep(3)
pygame.mixer.music.play(0)
Message = ""
Numeral = "5"
UpdateDisplay()
timepulse = 0.5
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "4"
UpdateDisplay()
timepulse = 0.4
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "3"
UpdateDisplay()
timepulse = 0.3
time.sleep(1)
pygame.mixer.music.play(0)
Numeral = "2"
UpdateDisplay()
timepulse = 0.2
time.sleep(1)
pygame.mixer.music.play(0)
time.sleep(0.1)
Numeral = "1"
UpdateDisplay()
timepulse = 0.1
time.sleep(1)
pygame.mixer.music.load('/home/pi/Desktop/camera.mp3')
pygame.mixer.music.play(0)
Numeral = ""
Message = "Smile!"
UpdateDisplay()
subimagecounter = subimagecounter+1
filename = 'image'
filename += 'imagecounter'
filename += '_'
filename += 'subimagecounter'
filename += '.jpg'
camera.capture(os.path.join(imagefolder,filename))
Message = "Working.."
UpdateDisplay()
im4 = PIL.Image.open(os.path.join(imagefolder,filename)).transpose(Image.FLIP_LEFT_RIGHT)
#Load the background template
bgimage = PIL.Image.open("/home/pi/Desktop/template.jpg")
#thumbnail the 4 images
im.thumbnail((560,400))
im2.thumbnail((560,400))
im3.thumbnail((560,400))
im4.thumbnail((560,400))
#paste the thumbnails to the background images
bgimage.paste(im,(15,20))
bgimage.paste(im2,(15,410))
bgimage.paste(im3,(15,820))
bgimage.paste(im4,(15,1230))
#two columns of 4
bgimage.paste(im,(620,20))
bgimage.paste(im2,(620,410))
bgimage.paste(im3,(620,820))
bgimage.paste(im4,(620,1230))
#Create the final filename
Final_Image_Name = os.path.join(imagefolder,"Final_"+'imagecounter'+".jpg")
#Save it to the usb drive
bgimage.save(os.path.join(imagefolder,"Final_"+'imagecounter'+".jpg"))
#Save a temp file, its faster to print(from the pi than usb)
bgimage.save('/home/pi/Desktop/tempprint.jpg')
#Connect to cups and select printer 0
conn = cups.Connection()
printers = conn.getPrinters()
printer_name = printers.keys()[0]
#Increment the large image counter
TotalImageCount = TotalImageCount + 1
Message = "Print..."
UpdateDisplay()
#print(the file)
printqueuelength = len(conn.getJobs())
#If multiple prints in the queue error
if printqueuelength > 1:
Message = "PRINT ERROR"
conn.enablePrinter(printer_name)
UpdateDisplay()
elif printqueuelength == 1:
SmallMessage = "Print Queue Full!"
conn.enablePrinter(printer_name)
UpdateDisplay()
conn.printFile(printer_name,'/home/pi/Desktop/tempprint.jpg',"PhotoBooth",{})
time.sleep(20)
Message = ""
UpdateDisplay()
timepulse = 999
#reset the shutter switch
while input_value == False:
input_value = gpio.input(22)
#we are exiting so stop preview
camera.stop_preview()
#launch the main thread
Thread(target=main, args=('Main',1)).start()
#launch the pulse thread
Thread(target=pulse, args=('Pulse',1)).start()
#sleap
time.sleep(5)
Python links
- Learn Python: https://pythonbasics.org/
- Python Tutorial: https://pythonprogramminglanguage.com