tao_quote_display/generate_image.py
2024-07-26 13:04:40 +02:00

140 lines
4.4 KiB
Python

from PIL import Image, ImageDraw, ImageFont
from datetime import date, timedelta
import io
import requests
# Read in the quotes
with open('Tao Te Ching.txt', 'r', encoding='utf-8') as f:
tao = [line.replace('\ufeff', '').strip() for line in f.readlines()]
# Pick the day to send and pick which quote to send
show_new_quote_frequency_days = 3
start_date = date(2024, 7, 26)
today = date.today()
yesterday = today - timedelta(days=1)
index_today = (today - start_date).days // show_new_quote_frequency_days
index_yesterday = (yesterday - start_date).days // show_new_quote_frequency_days
if index_today < 0 or not (index_today > index_yesterday):
print('not today')
exit()
if index_today >= len(tao):
print("we're done")
exit()
verse_index = index_today + 1
text = tao[verse_index-1]
# Generating the image
global_scale = 10
size = (134*8*global_scale, 181*8*global_scale)
margin = int(0.1*size[0])
text_box_size = (size[0] - 2*margin, size[1] - 2*margin)
font_path = "Compass 9.ttf"
image = Image.new('RGB', size, (0,0,0))
draw = ImageDraw.Draw(image)
fontsize = 40*global_scale
font = ImageFont.truetype(font_path, fontsize)
# Helper functions
def get_width(text, font):
return get_dims(text, font)[0]
def get_dims(text, font):
lines = text.split('\n')
width = 0
height = 0
for line in lines:
box = font.getbbox(line)
if box[2] - box[0] > width:
width = box[2] - box[0]
height += 1.2 * (box[3] - box[1])
return width, height
def get_ratio(text, font):
w, h = get_dims(text, font)
return w/h
# Finding where to add \n and which font size will fit the kindle screen best
words = text.split()
print(words)
current_ratio = None
previous_ratio = None
goal_ratio = text_box_size[0]/text_box_size[1]
wrapped_text = None
while wrapped_text is None or current_ratio is None or previous_ratio is None or (abs(goal_ratio - current_ratio) < abs(goal_ratio - previous_ratio) and get_dims(wrapped_text, font)[1] < text_box_size[1]):
lines = [[]]
word_index = 0
line_index = 0
while word_index < len(words):
if get_width(' '.join(lines[line_index]) + ' ' + words[word_index], font) >= text_box_size[0]:
break
while get_width(' '.join(lines[line_index]) + ' ' + words[word_index], font) < text_box_size[0]:
lines[line_index].append(words[word_index])
word_index += 1
if word_index >= len(words) - 1:
break
line_index += 1
lines.append([])
wrapped_text = '\n'.join([' '.join(line) for line in lines]).strip()
previous_ratio = current_ratio
current_ratio = get_ratio(wrapped_text, font)
fontsize += global_scale * 10
font = ImageFont.truetype(font_path, fontsize)
print(goal_ratio, current_ratio, fontsize, text_box_size, get_dims(wrapped_text, font))
# Stepping back the fontsize
fontsize -= global_scale * 20
font = ImageFont.truetype(font_path, fontsize)
lines = [[words[0]]]
word_index = 1
line_index = 0
while word_index < len(words):
while get_width(' '.join(lines[line_index]) + ' ' + words[word_index], font) < text_box_size[0]:
lines[line_index].append(words[word_index])
word_index += 1
if word_index >= len(words) - 1:
break
line_index += 1
lines.append([])
print(goal_ratio, current_ratio, fontsize, text_box_size, get_dims(wrapped_text, font))
print(lines)
# Drawing the quote and the attribution
wrapped_text = '\n'.join([' '.join(line) for line in lines])
draw.multiline_text((margin, margin), wrapped_text, font=font, fill=(255,255,255), stroke_width=int(0.1*global_scale))
attribution = f'Verse {verse_index} from "Tao Te Ching" translated by Carol Deppe. Font "Compass" by somepx.'
fontsize = 10*global_scale
font = ImageFont.truetype(font_path, fontsize)
while get_width(attribution, font) < size[0]*0.9:
fontsize += global_scale
font = ImageFont.truetype(font_path, fontsize)
w, h = get_dims(attribution, font)
print(w, h, size)
attr_margin = int((size[0]-w)/2)
draw.multiline_text((attr_margin, size[1]-h*2.5), attribution, font=font, fill=(255,255,255), stroke_width=int(0.1*global_scale))
image = image.resize((size[0]//global_scale, size[1]//global_scale), resample=Image.NEAREST)
# image.save("image.png")
# And off to the kindle
image_bytes = io.BytesIO()
image.save(image_bytes, format='PNG')
image_bytes = image_bytes.getvalue()
requests.post('http://kindle.sn0w.cx/data', data=image_bytes)