Text is now vertically aligned and GPIO channel for lamp added

This commit is contained in:
Balthasar Reuter
2015-06-16 22:46:58 +02:00
parent eb2344d066
commit d40ba4c589
2 changed files with 67 additions and 19 deletions

View File

@@ -35,9 +35,9 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.8262427"
inkscape:cx="1134.3559"
inkscape:cy="701.47771"
inkscape:zoom="0.58424182"
inkscape:cx="667.80608"
inkscape:cy="717.44673"
inkscape:document-units="px"
inkscape:current-layer="layer5"
showgrid="false"
@@ -54,7 +54,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -89,7 +89,7 @@
transform="translate(0,-1084.252)">
<g
id="g4161"
transform="matrix(0,-1.0006094,1.0009564,0,-484.38195,1945.4764)"
transform="matrix(0,-1.0006094,1.0009564,0,-484.38195,1941.4764)"
style="display:inline;stroke:#0000ff;stroke-width:0.99921769;stroke-opacity:1">
<rect
y="642.01733"
@@ -165,7 +165,7 @@
<rect
transform="matrix(0,-1,1,0,0,0)"
y="168.53157"
x="-1898.7059"
x="-1893.5669"
height="332.38846"
width="555.63757"
id="rect4246"

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -49,6 +49,9 @@ gpio_shutdown_channel = 24 # pin 18 in all Raspi-Versions
# GPIO channel of switch to take pictures
gpio_trigger_channel = 23 # pin 16 in all Raspi-Versions
# GPIO output channel for (blinking) lamp
gpio_lamp_channel = 4 # pin 7 in all Raspi-Versions
# PyGame event used to detect GPIO triggers
gpio_pygame_event = pygame.USEREVENT
@@ -102,7 +105,7 @@ class TextRectException:
def __str__(self):
return self.message
def render_textrect(string, font, rect, text_color, background_color, justification=0):
def render_textrect(string, font, rect, text_color, background_color, justification=0, valign=0):
"""Returns a surface containing the passed text string, reformatted
to fit within the given rect, word-wrapping as necessary. The text
will be anti-aliased.
@@ -120,6 +123,9 @@ def render_textrect(string, font, rect, text_color, background_color, justificat
justification - 0 (default) left-justified
1 horizontally centered
2 right-justified
valign - 0 (default) top aligned
1 vertically centered
2 bottom aligned
Returns the following values:
@@ -134,6 +140,7 @@ def render_textrect(string, font, rect, text_color, background_color, justificat
# Create a series of lines that will fit on the provided
# rectangle.
accumulated_height = 0
for requested_line in requested_lines:
if font.size(requested_line)[0] > rect.width:
words = requested_line.split(' ')
@@ -149,12 +156,29 @@ def render_textrect(string, font, rect, text_color, background_color, justificat
if font.size(test_line)[0] < rect.width:
accumulated_line = test_line
else:
accumulated_height += font.size(test_line)[1]
final_lines.append(accumulated_line)
accumulated_line = word + " "
accumulated_height += font.size(accumulated_line)[1]
final_lines.append(accumulated_line)
else:
else:
accumulated_height += font.size(requested_line)[1]
final_lines.append(requested_line)
# Check height of the text and align vertically
if accumulated_height >= rect.height:
raise TextRectException, "Once word-wrapped, the text string was too tall to fit in the rect."
if valign == 0:
voffset = 0
elif valign == 1:
voffset = int((rect.height - accumulated_height) / 2)
elif valign == 2:
voffset = rect.height - accumulated_height
else:
raise TextRectException, "Invalid valign argument: " + str(valign)
# Let's try to write the text out on the surface.
surface = pygame.Surface(rect.size)
@@ -162,16 +186,14 @@ def render_textrect(string, font, rect, text_color, background_color, justificat
accumulated_height = 0
for line in final_lines:
if accumulated_height + font.size(line)[1] >= rect.height:
raise TextRectException, "Once word-wrapped, the text string was too tall to fit in the rect."
if line != "":
tempsurface = font.render(line, 1, text_color)
if justification == 0:
surface.blit(tempsurface, (0, accumulated_height))
surface.blit(tempsurface, (0, voffset + accumulated_height))
elif justification == 1:
surface.blit(tempsurface, ((rect.width - tempsurface.get_width()) / 2, accumulated_height))
surface.blit(tempsurface, ((rect.width - tempsurface.get_width()) / 2, voffset + accumulated_height))
elif justification == 2:
surface.blit(tempsurface, (rect.width - tempsurface.get_width(), accumulated_height))
surface.blit(tempsurface, (rect.width - tempsurface.get_width(), voffset + accumulated_height))
else:
raise TextRectException, "Invalid justification argument: " + str(justification)
accumulated_height += font.size(line)[1]
@@ -227,9 +249,9 @@ class GUI_PyGame:
# Choose font
font = pygame.font.Font(None, 144)
# Create rectangle for text
rect = pygame.Rect((40, 40, self.size[0] - 40, self.size[1] - 40))
rect = pygame.Rect((0, 0, self.size[0], self.size[1]))
# Render text
text = render_textrect(msg, font, rect, color, bg, 1)
text = render_textrect(msg, font, rect, color, bg, 1, 1)
self.screen.blit(text, rect.topleft)
def mainloop(self, filename):
@@ -241,7 +263,7 @@ class GUI_PyGame:
# Show idle-picture and message
if filename != None:
self.show_picture(filename)
self.show_message("\n\nHit the button!")
self.show_message("Hit the button!")
# Render everything
self.apply()
# Wait for event
@@ -300,10 +322,13 @@ class Camera:
def assemble_pictures(input_filenames, output_filename):
"""Assembles four pictures into a 2x2 grid"""
# Thumbnail size of pictures
size = (int(image_size[0]/2),int(image_size[1]/2))
# Create output image
output_image = Image.new('RGB', image_size)
# Load images and resize them
for i in range(2):
for j in range(2):
@@ -312,10 +337,14 @@ def assemble_pictures(input_filenames, output_filename):
img.thumbnail(size)
offset = (j * size[0], i * size[1])
output_image.paste(img, offset)
output_image.save(output_filename, "JPEG")
def take_picture():
"""Implements the picture taking routine"""
# Disable the lamp
set_lamp(0)
# Show pose message
display.clear()
if image_pose != None:
@@ -327,13 +356,13 @@ def take_picture():
# Countdown
for i in range(3):
display.clear()
display.show_message("\n\n" + str(3 - i))
display.show_message(str(3 - i))
display.apply()
sleep(1)
# Show 'Cheese'
display.clear()
display.show_message("\n\nS M I L E !")
display.show_message("S M I L E !")
display.apply()
# Extract display and image sizes
@@ -360,11 +389,16 @@ def take_picture():
display.apply()
sleep(display_time)
# Reenable lamp
set_lamp(1)
def handle_keypress(key):
"""Implements the actions for the different keypress events"""
# Exit the application
if key == ord('q'):
teardown()
# Take pictures
elif key == ord('c'):
take_picture()
@@ -377,12 +411,14 @@ def handle_mousebutton(key, pos):
def handle_gpio_event(channel):
"""Implements the actions taken for a GPIO event"""
if channel == gpio_trigger_channel:
take_picture()
elif channel == gpio_shutdown_channel:
display.clear()
print("Shutting down!")
display.show_message("\n\nShutting down!")
display.show_message("Shutting down!")
display.apply()
sleep(1)
teardown()
@@ -401,13 +437,19 @@ def setup_gpio():
# Display initial information
print("Your Raspberry Pi is board revision " + str(GPIO.RPI_INFO['P1_REVISION']))
print("RPi.GPIO version is " + str(GPIO.VERSION))
# Choose BCM numbering system
GPIO.setmode(GPIO.BCM)
# Setup the trigger channel as input and listen for events
GPIO.setup(gpio_trigger_channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(gpio_shutdown_channel, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(gpio_trigger_channel, GPIO.RISING, callback=handle_gpio, bouncetime=200)
GPIO.add_event_detect(gpio_shutdown_channel, GPIO.RISING, callback=handle_gpio, bouncetime=200)
# Setup the lamp channel as output
GPIO.setup(gpio_lamp_channel, GPIO.OUT)
GPIO.output(gpio_lamp_channel, GPIO.LOW)
else:
print("Warning: RPi.GPIO could not be loaded. GPIO disabled.")
@@ -415,6 +457,11 @@ def handle_gpio(channel):
"""Interrupt handler for GPIO events"""
display.trigger_event(gpio_pygame_event, channel)
def set_lamp(status=0):
"""Switch the lamp on"""
if gpio_enabled:
GPIO.output(gpio_lamp_channel, GPIO.HIGH if status==1 else GPIO.LOW)
def teardown(exit_code=0):
display.teardown()
if gpio_enabled:
@@ -425,6 +472,7 @@ def main():
setup_gpio()
while True:
try:
set_lamp(1)
display.mainloop(image_idle)
except CameraException as e:
handle_exception(e.message)