141 lines
4.4 KiB
Python
141 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)
|