#!/usr/bin/env python3 """Build the README's computer-and-phone still from the two raw shots. Run docs/demo/README.md's capture steps first (dark, 2x), then: python3 docs/demo/composite.py """ from PIL import Image, ImageDraw from pathlib import Path root = Path(__file__).resolve().parents[2] shots = root / "shots" / "readme" BG = (22, 22, 22) # the app's dark pane, so the canvas reads as one screen desk = Image.open(shots / "ask.png").convert("RGB") # the approval card phone = Image.open(shots / "phone.png").convert("RGB") # the sign-in page W, pad, gap, phone_w = 960, 24, 24, 264 phone_h = round(phone.size[1] * phone_w / phone.size[0]) desk_w = W - 2 * pad - gap - phone_w desk_h = round(desk.size[1] * desk_w / desk.size[0]) H = pad + max(phone_h, desk_h) + pad def rounded(im, r): mask = Image.new("L", im.size, 0) ImageDraw.Draw(mask).rounded_rectangle([0, 0, *im.size], radius=r, fill=255) out = Image.new("RGB", im.size, BG) out.paste(im, (0, 0), mask) return out, mask canvas = Image.new("RGB", (W, H), BG) im, mask = rounded(desk.resize((desk_w, desk_h), Image.LANCZOS), 12) canvas.paste(im, (pad, pad + (phone_h - desk_h) // 2), mask) im, mask = rounded(phone.resize((phone_w, phone_h), Image.LANCZOS), 18) canvas.paste(im, (W - pad - phone_w, pad), mask) out = shots / "computer-phone.png" canvas.save(out, optimize=True) print(out.relative_to(root), canvas.size)