/
pbooth.py
executable file
·234 lines (204 loc) · 7.21 KB
/
pbooth.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# boothy - Photobooth application for Raspberry Pi
# developed by Kenneth Centurion
#
# This application will take 3 images with PHOTO_DELAY seconds between.
# Will have text overlay on the screen with a countdown. Will then merge
# the 3 images with a template fourth image "4logo.png" in a grid. The final
# image is then sent to the printer using the CUPs API.
import picamera
import itertools
import cups
import subprocess
import os
from shutil import copyfile
import sys
import time
import logging
import RPi.GPIO as GPIO
from PIL import Image, ImageDraw, ImageFont
IMG1 = "1.jpg"
IMG2 = "2.jpg"
IMG3 = "3.jpg"
CurrentWorkingDir= "/usr/local/src/boothy"
IMG4 = "4logo.png"
logDir = "logs"
archiveDir = "photos"
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
IMAGE_WIDTH = 640
IMAGE_HEIGHT = 480
BUTTON_PIN = 26
LED_PIN = 19 #connected to external 12v.
PHOTO_DELAY = 8
overlay_renderer = None
buttonEvent = False
#setup GPIOs
GPIO.setmode(GPIO.BCM)
GPIO.setup(BUTTON_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(LED_PIN, GPIO.OUT)
#print the image
def printPic(fileName):
addPreviewOverlay(100,200,55,"printing...")
conn = cups.Connection()
printers = conn.getPrinters()
default_printer = printers.keys()[0]
cups.setUser('pi')
conn.printFile (default_printer, fileName, "boothy", {'fit-to-page':'True'})
logging.info("Print job successfully created.");
#merges the 4 images
def convertMergeImages(fileName):
addPreviewOverlay(150,200,55,"merging images...")
#now merge all the images
subprocess.call(["montage",
IMG1,IMG2,IMG3,IMG4,
"-geometry", "+2+2",
fileName])
logging.info("Images have been merged.")
def deleteImages(fileName):
logging.info("Deleting any old images.")
if os.path.isfile(IMG1):
os.remove(IMG1)
if os.path.isfile(IMG2):
os.remove(IMG2)
if os.path.isfile(IMG3):
os.remove(IMG3)
if os.path.isfile(fileName):
os.remove(fileName);
def cleanUp():
GPIO.cleanup()
def archiveImage(fileName):
logging.info("Saving off image: "+fileName)
copyfile(fileName,archiveDir+"/"+fileName)
def countdownFrom(secondsStr):
secondsNum = int(secondsStr)
if secondsNum >= 0 :
while secondsNum > 0 :
addPreviewOverlay(300,100,240,str(secondsNum))
time.sleep(1)
secondsNum=secondsNum-1
def captureImage(imageName):
addPreviewOverlay(150,200,100,"smile! :)")
#save image
camera.capture(imageName, resize=(IMAGE_WIDTH, IMAGE_HEIGHT))
logging.info("Image "+imageName+" captured.")
def addPreviewOverlay(xcoord,ycoord,fontSize,overlayText):
global overlay_renderer
img = Image.new("RGB", (SCREEN_WIDTH, SCREEN_HEIGHT))
draw = ImageDraw.Draw(img)
draw.font = ImageFont.truetype(
"/usr/share/fonts/truetype/freefont/FreeSerif.ttf",fontSize)
draw.text((xcoord,ycoord), overlayText, (255, 20, 147))
if not overlay_renderer:
# Note: The call to add_overlay has changed since picamera v.1.10.
# If you have a new version of picamera, then please change the
# first parameter to: img.tobytes()
#
overlay_renderer = camera.add_overlay(img.tostring(),
layer=3,
size=img.size,
alpha=128);
else:
overlay_renderer.update(img.tostring())
#run a full series
def play():
print "Starting play sequence"
fileName = time.strftime("%Y%m%d-%H%M%S")+".jpg"
print "Created filename: "+fileName
#turn on flash
GPIO.output(LED_PIN,GPIO.HIGH)
countdownFrom(PHOTO_DELAY)
captureImage(IMG1)
time.sleep(1)
countdownFrom(PHOTO_DELAY)
captureImage(IMG2)
time.sleep(1)
countdownFrom(PHOTO_DELAY)
captureImage(IMG3)
time.sleep(1)
#turn off flash
GPIO.output(LED_PIN,GPIO.LOW)
convertMergeImages(fileName)
time.sleep(1)
printPic(fileName)
time.sleep(15)
archiveImage(fileName)
deleteImages(fileName)
def initCamera(camera):
logging.info("Initializing camera.")
#camera settings
camera.resolution = (SCREEN_WIDTH, SCREEN_HEIGHT)
camera.framerate = 24
camera.sharpness = 0
camera.contrast = 0
camera.brightness = 50
camera.saturation = 0
camera.ISO = 0
camera.video_stabilization = False
camera.exposure_compensation = 0
camera.exposure_mode = 'auto'
camera.meter_mode = 'average'
camera.awb_mode = 'auto'
camera.image_effect = 'none'
camera.color_effects = None
camera.rotation = 0
camera.hflip = False
camera.vflip = True
camera.crop = (0.0, 0.0, 1.0, 1.0)
def initLogger(output_dir):
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
# create console handler and set level to info
handler = logging.StreamHandler()
handler.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
# create error file handler and set level to error
handler = logging.FileHandler(output_dir+"/"+time.strftime("%Y%m%d")+"_error.log","w", encoding=None, delay="true")
handler.setLevel(logging.ERROR)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
# create debug file handler and set level to debug
handler = logging.FileHandler(output_dir+"/"+time.strftime("%Y%m%d")+"_debug.log","w", encoding=None, delay="true")
handler.setLevel(logging.DEBUG)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
handler.setFormatter(formatter)
logger.addHandler(handler)
def onButtonPress():
logging.info("Big red button pressed!")
play()
#reset the initial welcome message
addPreviewOverlay(20,200,55,"Press red button to begin!")
def onButtonDePress():
logging.info("Big red button de-pressed!")
#start flow
with picamera.PiCamera() as camera:
os.chdir(CurrentWorkingDir)
try:
initLogger(logDir)
initCamera(camera)
GPIO.output(LED_PIN,GPIO.LOW)
logging.info("Starting preview")
camera.start_preview()
addPreviewOverlay(20,200,55,"Press red button to begin!")
logging.info("Starting application loop")
while True:
input_state = GPIO.input(BUTTON_PIN)
if input_state == True :
if buttonEvent == False :
buttonEvent = True
onButtonPress()
else :
if buttonEvent == True :
buttonEvent = False
onButtonDePress()
except BaseException:
logging.error("Unhandled exception : " , exc_info=True)
camera.close()
cleanUp()
finally:
logging.info("quitting...")
cleanUp()
camera.close()
#end