Match photo selection and rendered canvas to device rotation
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
"""Resolve a device's visual canvas without coupling rendering to its driver."""
|
||||
|
||||
|
||||
def frame_canvas(display, orientation=None):
|
||||
width, height = display.width, display.height
|
||||
if orientation == "landscape":
|
||||
return max(width, height), min(width, height)
|
||||
if orientation == "portrait":
|
||||
return min(width, height), max(width, height)
|
||||
return (height, width) if display.rotation % 180 == 90 else (width, height)
|
||||
@@ -7,23 +7,40 @@ from PIL import Image, ImageDraw
|
||||
from pigway_frame_flow.renderers.images import convert
|
||||
|
||||
|
||||
def render_captioned_photo(data, caption, font_loader, fit="contain", profile="color"):
|
||||
photo_data = convert(data, fit, profile, size=(1200, 1280))
|
||||
canvas = Image.new("RGB", (1200, 1600), "white")
|
||||
def render_captioned_photo(
|
||||
data, caption, font_loader, fit="contain", profile="color", *, size=(1200, 1600)
|
||||
):
|
||||
width, height = size
|
||||
landscape = width > height
|
||||
caption_height = 240 if landscape else 320
|
||||
photo_height = height - caption_height
|
||||
photo_data = convert(data, fit, profile, size=(width, photo_height))
|
||||
canvas = Image.new("RGB", size, "white")
|
||||
with Image.open(BytesIO(photo_data)) as photo:
|
||||
canvas.paste(photo, (0, 0))
|
||||
draw = ImageDraw.Draw(canvas)
|
||||
lines = [(caption["title"], 1320, 52), (caption["date"], 1410, 40)]
|
||||
if caption.get("place"):
|
||||
lines.append((caption["place"], 1480, 38))
|
||||
for text, y, size in lines:
|
||||
font = font_loader(size)
|
||||
while size > 24 and draw.textlength(text, font=font) > 1080:
|
||||
size -= 2
|
||||
font = font_loader(size)
|
||||
while draw.textlength(text, font=font) > 1080 and text:
|
||||
rows = (
|
||||
[(24, 44), (88, 36), (140, 34)]
|
||||
if landscape
|
||||
else [(40, 52), (130, 40), (200, 38)]
|
||||
)
|
||||
values = [caption["title"], caption["date"], caption.get("place", "")]
|
||||
for text, (offset, font_size) in zip(values, rows, strict=True):
|
||||
if not text:
|
||||
continue
|
||||
font = font_loader(font_size)
|
||||
while font_size > 24 and draw.textlength(text, font=font) > width - 120:
|
||||
font_size -= 2
|
||||
font = font_loader(font_size)
|
||||
while draw.textlength(text, font=font) > width - 120 and text:
|
||||
text = text[:-2] + "…"
|
||||
draw.text((600, y), text, font=font, fill="black", anchor="mt")
|
||||
draw.text(
|
||||
(width / 2, photo_height + offset),
|
||||
text,
|
||||
font=font,
|
||||
fill="black",
|
||||
anchor="mt",
|
||||
)
|
||||
out = BytesIO()
|
||||
canvas.save(out, "JPEG", quality=93, optimize=True)
|
||||
return out.getvalue()
|
||||
|
||||
Reference in New Issue
Block a user