diff --git a/render.py b/render.py index 1aee92b..a24ccb3 100644 --- a/render.py +++ b/render.py @@ -10,7 +10,7 @@ import argparse import math import random from html import escape as html_escape -from PIL import Image, ImageSequence +from PIL import Image, ImageOps, ImageSequence # ── Character palettes sorted dark → light ────────────────────────────── PALETTES = { @@ -65,13 +65,18 @@ def get_luminance(r: int, g: int, b: int) -> float: def _prepare_frame(img: Image.Image, width: int, bg: str) -> Image.Image: """Composite alpha onto background and resize for rendering.""" + # Apply EXIF orientation (phone photos come rotated without this) + img = ImageOps.exif_transpose(img) img = img.convert("RGBA") bg_color = (0, 0, 0, 255) if bg == "dark" else (255, 255, 255, 255) background = Image.new("RGBA", img.size, bg_color) background.paste(img, mask=img.split()[3]) img = background.convert("RGB") + # Monospace chars in browser: ~0.6 width-to-height ratio at font-size 8px, line-height 1.05 + # So each char cell is roughly 4.8px wide x 8.4px tall → ratio 0.57 + char_aspect = 0.55 aspect = img.height / img.width - height = max(1, int(width * aspect * 0.45)) + height = max(1, int(width * aspect * char_aspect)) return img.resize((width, height), Image.LANCZOS)