Inky Impression Text + image not showing well

Hi,

i am setting up a inky impression 5.7
the idea is to have a screensaver with a central image from jpg and calendar information extracted from my google calendar.
I setup the text element and it was going fine, but now i added the picture jpg and i have problem with its colours, they are showing bad. but in a code that shows only the image, it works fine. i am trying to find a solution, is it possible that the display cannot render two different things: image + text element?
i am not a developer, i am using gpt to work on it. see the image attached

Could you share some code? I have a similar application and I have no problems rendering text and images at the same time. The rendering takes place in PIL and the final result is then dumped onto the Inky.

(Not related to this problem: I would also love to see your code connecting to your google calendar. This is on my todo-list already for a long time and I am just to lazy (or busy with other things) to actually implement it)

from googleapiclient.discovery import build
from inky.auto import auto
from PIL import Image, ImageDraw, ImageFont
from datetime import datetime, timedelta

# My API key
API_KEY = 'xxxx'
CALENDAR_ID = 'xxxx'

# Initialize the Google Calendar API client
service = build('calendar', 'v3', developerKey=API_KEY)

# Automatically detect the display
inky_display = auto()
width, height = inky_display.resolution

# Load the image
img = Image.open('/home/giovanni/onesmall.jpg')

# Resize the image to 600x350 pixels
img = img.resize((600, 350), resample=Image.LANCZOS)

# Create a new image for the background with the same mode and size as the display
background = Image.new("P", (width, height), color=inky_display.WHITE)

# Calculate position to center the 600x350 image on the 600x448 background
x_position = 0  # Centered horizontally (600 width fits exactly)
y_position = (height - 350) // 2  # Centered vertically

# Paste the resized image onto the background at the calculated position
background.paste(img, (x_position, y_position))

# Convert the image to the appropriate color mode for the display
if inky_display.colour == "blackwhite":
    background = background.convert("1")
elif inky_display.colour == "red":
    background = background.convert("P")
    background = background.quantize(colors=2, method=1, kmeans=2, palette=inky_display.PALETTE_RED)
elif inky_display.colour == "yellow":
    background = background.convert("P")
    background = background.quantize(colors=2, method=1, kmeans=2, palette=inky_display.PALETTE_YELLOW)
elif inky_display.colour == "multicolor":
    background = background.convert("P")
    background = background.quantize(colors=4, method=1, kmeans=2, palette=inky_display.PALETTE_MULTI)

# Set the saturation level (if needed)
inky_display.set_image(background, saturation=1)

# Define fonts
font_large = ImageFont.truetype("/usr/share/fonts/truetype/roboto/Roboto-Bold.ttf", 65)
font_medium = ImageFont.truetype("/usr/share/fonts/truetype/roboto/Roboto-Bold.ttf", 20)
font_small = ImageFont.truetype("/usr/share/fonts/truetype/roboto/Roboto-Regular.ttf", 18)
font_xsmall = ImageFont.truetype("/usr/share/fonts/truetype/roboto/Roboto-Regular.ttf", 14)

# Draw on the image directly
draw = ImageDraw.Draw(background)

# Display the current date at the top left
today = datetime.now()
day_number = today.strftime("%d")
day_name = today.strftime("%A")
month_name = today.strftime("%B")

# Set positions for the day number and the day/month texts
day_number_x = 5
ascent, descent = font_large.getmetrics()
day_number_y = 50 - ascent

day_name_x = day_number_x + 80  # Adjust for space between number and text
day_name_y = day_number_y + 20  # Align vertically with the number
month_name_y = day_name_y + 20  # Position below the day name

# Draw the date
draw.text((day_number_x, day_number_y), day_number, inky_display.RED, font=font_large)
draw.text((day_name_x, day_name_y), day_name, inky_display.BLACK, font=font_medium)
draw.text((day_name_x, month_name_y), month_name, inky_display.BLACK, font=font_medium)

# Display the current week at the bottom
days_of_week = ["M", "T", "W", "T", "F", "S", "S"]
start_of_week = today - timedelta(days=today.weekday())  # Calculate Monday of the current week
end_of_week = start_of_week + timedelta(days=7)

# Fetch events for the current week from the public calendar
events_result = service.events().list(
    calendarId=CALENDAR_ID,
    timeMin=start_of_week.isoformat() + 'Z',
    timeMax=end_of_week.isoformat() + 'Z',
    singleEvents=True,
    orderBy='startTime'
).execute()
events = events_result.get('items', [])

# Prepare a dictionary to store events by day
events_by_day = {start_of_week.date() + timedelta(days=i): [] for i in range(7)}

for event in events:
    start = event['start'].get('dateTime', event['start'].get('date'))
    start_date = datetime.fromisoformat(start).date()
    if start_date in events_by_day:
        events_by_day[start_date].append(event['summary'])

# Loop over the next 7 days to display day numbers and events
for i in range(7):
    day = start_of_week + timedelta(days=i)
    day_label = day.strftime("%d")  # e.g., "19"
    day_initial = day.strftime("%a")[0]  # e.g., "M" for Monday

    # Set color for the current day
    if day.date() == today.date():
        day_color = inky_display.RED if i in [5, 6] else inky_display.BLACK
        # Draw a thick red line under the day number (only for the current day)
        line_y = height - 65
        section_width = width // 7  # Calculate the width of one section
        draw.line((i * section_width, line_y, (i + 1) * section_width, line_y), fill=inky_display.RED, width=4)
    else:
        day_color = inky_display.BLACK if i < 5 else inky_display.RED

    # Calculate x position for each section (centered within each section)
    section_width = width // 7
    x_position = i * section_width

    # Calculate positions for day number and initial to the right of the day number
    day_label_bbox = draw.textbbox((0, 0), day_label, font=font_medium)
    day_initial_bbox = draw.textbbox((0, 0), day_initial, font=font_medium)

    day_label_width = day_label_bbox[2] - day_label_bbox[0]
    day_initial_width = day_initial_bbox[2] - day_initial_bbox[0]
    
    # Calculate the x position for day_initial to the right of day_label
    day_label_x = x_position + (section_width - (day_label_width + day_initial_width + 5)) // 2
    day_initial_x = day_label_x + day_label_width + 5
    
    # Draw the day number and weekday initial
    draw.text((day_label_x, height - 60), day_label, day_color, font=font_medium)
    draw.text((day_initial_x, height - 60), day_initial, day_color, font=font_medium)
    
    # Calculate position for the bullet point text, left-aligned under the day number
    y_position = height - 35

    # Display a maximum of two events for the current day
    events_for_day = events_by_day.get(day.date(), [])[:2]  # Get at most 2 events
    for event_title in events_for_day:
        draw.text((x_position + 10, y_position), f"• {event_title}", inky_display.BLACK, font=font_xsmall)
        y_position += 20  # Move down for the next event

# Set the updated image on the display
inky_display.set_image(background)

# Display the image on the Inky display
inky_display.show()

If you enclose your code in triple backticks (```) or use the ‘preformatted text’ formatting option from the toolbar it will display blocks of code it in a sensible way - I’ve edited those in for you this time :)

1 Like

Something in your code is strange. The Inky libraries for example don’t use multicolor, only multi. And the Inky-Impression is 7 colors (aka “colours”) and not 4 colors. So it might be that your code does not quantize the image at all.

Just be aware that GPT sometimes just invents things that don’t exist.

hi @bablokb yes you are right, chat gpt works weird. but because i am not a developer is my main help :D
i noticed that the script indicates only 4 colours. if you have a code example that instead reproduce correctly the jpg image on the inky it would be great. i tried to find on the pimoroni github but not successed.

I only use pre-quantized images.

Have you tried the image.py example from the inky GitHub repository?