Hi, I’m a first-time requester here, but I’ve been lurking for a while as I enjoy tinkering with the Badger 2040. I have a real novice question, but I’m attempting to add two images to a badge script for the first time, and I’m hitting an issue. It’s likely super simple, but it’s stumped me.
I’m using the example code but attempting to pull in two images, the default photo (badge.jpg) and an image to replace the default ‘COMPANY’ text with ‘company_image’ (company_logo.png). But I keep getting Errno 2 ENOENT when it comes to draw the image. For context the DEFAULT_TEXT matches the BADGE_PATH.
I’m happy to investigate the answer rather than be given the answer if anyone can guide me to the relevant knowledgebase where I can learn.
import badger2040
import jpegdec
# Global Constants
WIDTH = badger2040.WIDTH
HEIGHT = badger2040.HEIGHT
IMAGE_WIDTH = 104
COMPANY_IMAGE_WIDTH = 200 # Width for the new company image
COMPANY_IMAGE_HEIGHT = 30 # Introducing company logo height
COMPANY_HEIGHT = 30
DETAILS_HEIGHT = 20
NAME_HEIGHT = HEIGHT - COMPANY_HEIGHT - (DETAILS_HEIGHT * 2) - 2
TEXT_WIDTH = WIDTH - IMAGE_WIDTH - 1
COMPANY_TEXT_SIZE = 0.6
DETAILS_TEXT_SIZE = 0.5
LEFT_PADDING = 5
NAME_PADDING = 20
DETAIL_SPACING = 10
BADGE_PATH = "/badges/badge2.txt"
DEFAULT_TEXT = """mustelid inc
H. Badger
RP2040
2MB Flash
E ink
296x128px
/badges/badge.jpg
/badges/company_logo.png
"""
# ------------------------------
# Utility functions
# ------------------------------
# Reduce the size of a string until it fits within a given width
def truncatestring(text, text_size, width):
while True:
length = display.measure_text(text, text_size)
if length > 0 and length > width:
text = text[:-1]
else:
text += ""
return text
# ------------------------------
# Drawing functions
# ------------------------------
# Draw the badge, including user text and images
def draw_badge():
display.set_pen(0)
display.clear()
# Draw badge image
jpeg.open_file(badge_image)
jpeg.decode(WIDTH - IMAGE_WIDTH, 0)
# Draw a border around the badge image
display.set_pen(0)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - 1, 0)
display.line(WIDTH - IMAGE_WIDTH, 0, WIDTH - IMAGE_WIDTH, HEIGHT - 1)
display.line(WIDTH - IMAGE_WIDTH, HEIGHT - 1, WIDTH - 1, HEIGHT - 1)
display.line(WIDTH - 1, 0, WIDTH - 1, HEIGHT - 1)
# Draw the company logo image
jpeg.open_file(company_image)
jpeg.decode(LEFT_PADDING, 0)
# Draw the company text if needed
display.set_pen(15)
display.set_font("serif")
display.text(company, LEFT_PADDING + COMPANY_IMAGE_WIDTH + 5, (COMPANY_HEIGHT // 2) + 1, WIDTH, COMPANY_TEXT_SIZE)
# Draw a white background behind the name
display.set_pen(15)
display.rectangle(1, COMPANY_HEIGHT + 1, TEXT_WIDTH, NAME_HEIGHT)
# Draw the name, scaling it based on the available width
display.set_pen(0)
display.set_font("sans")
name_size = 2.0 # A sensible starting scale
while True:
name_length = display.measure_text(name, name_size)
if name_length >= (TEXT_WIDTH - NAME_PADDING) and name_size >= 0.1:
name_size -= 0.01
else:
display.text(name, (TEXT_WIDTH - name_length) // 2, (NAME_HEIGHT // 2) + COMPANY_HEIGHT + 1, WIDTH, name_size)
break
# Draw white backgrounds behind the details
display.set_pen(15)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT * 2, TEXT_WIDTH, DETAILS_HEIGHT - 1)
display.rectangle(1, HEIGHT - DETAILS_HEIGHT, TEXT_WIDTH, DETAILS_HEIGHT - 1)
# Draw the first detail's title and text
display.set_pen(0)
display.set_font("sans")
name_length = display.measure_text(detail1_title, DETAILS_TEXT_SIZE)
display.text(detail1_title, LEFT_PADDING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE)
display.text(detail1_text, 5 + name_length + DETAIL_SPACING, HEIGHT - ((DETAILS_HEIGHT * 3) // 2), WIDTH, DETAILS_TEXT_SIZE)
# Draw the second detail's title and text
name_length = display.measure_text(detail2_title, DETAILS_TEXT_SIZE)
display.text(detail2_title, LEFT_PADDING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE)
display.text(detail2_text, LEFT_PADDING + name_length + DETAIL_SPACING, HEIGHT - (DETAILS_HEIGHT // 2), WIDTH, DETAILS_TEXT_SIZE)
display.update()
# ------------------------------
# Program setup
# ------------------------------
# Create a new Badger and set it to update NORMAL
display = badger2040.Badger2040()
display.led(128)
display.set_update_speed(badger2040.UPDATE_NORMAL)
display.set_thickness(2)
jpeg = jpegdec.JPEG(display.display)
# Open the badge file
try:
badge = open(BADGE_PATH, "r")
except OSError:
with open(BADGE_PATH, "w") as f:
f.write(DEFAULT_TEXT)
f.flush()
badge = open(BADGE_PATH, "r")
# Read in the next 7 lines
company = badge.readline() # "mustelid inc"
name = badge.readline() # "H. Badger"
detail1_title = badge.readline() # "RP2040"
detail1_text = badge.readline() # "2MB Flash"
detail2_title = badge.readline() # "E ink"
detail2_text = badge.readline() # "296x128px"
badge_image = badge.readline() # /badges/badge.jpg
company_image = badge.readline() # /badges/company_logo.jpg
# Truncate all of the text (except for the name as that is scaled)
company = truncatestring(company, COMPANY_TEXT_SIZE, TEXT_WIDTH)
detail1_title = truncatestring(detail1_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail1_text = truncatestring(detail1_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail1_title, DETAILS_TEXT_SIZE))
detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
# ------------------------------
# Main program
# ------------------------------
draw_badge()
while True:
# Sometimes a button press or hold will keep the system
# powered *through* HALT, so latch the power back on.
display.keepalive()
# If on battery, halt the Badger to save power, it will wake up if any of the front buttons are pressed
display.halt()