#!/usr/bin/env python3 """Fit raw device captures to the Play Store's phone screenshot rules. python3 tools/prepare_screenshots.py ... --out store/ A capture off the emulator is 1080x2220, which is 2.06:1 — just past the 2:1 that Play accepts, so uploading one as-is risks a rejection over 40 pixels. Rather than crop the app's own chrome away, each shot is scaled to fit a 1080x1920 canvas and the leftover width is filled with the screenshot's own corner colour. Nothing is lost, nothing is stretched, and the fill matches the app background closely enough that the seam doesn't read as a border. """ import sys from pathlib import Path from PIL import Image CANVAS = (1080, 1920) def prepare(source: Path, destination: Path) -> None: shot = Image.open(source).convert("RGB") # The top-left pixel is app background on every screen we capture, which # makes it a better fill than any colour picked by hand. fill = shot.getpixel((0, 0)) scale = min(CANVAS[0] / shot.width, CANVAS[1] / shot.height) resized = shot.resize( (round(shot.width * scale), round(shot.height * scale)), Image.LANCZOS ) canvas = Image.new("RGB", CANVAS, fill) canvas.paste( resized, ((CANVAS[0] - resized.width) // 2, (CANVAS[1] - resized.height) // 2) ) canvas.save(destination, "PNG", optimize=True) print(f"{destination.name}: {shot.size[0]}x{shot.size[1]} -> {CANVAS[0]}x{CANVAS[1]}") def main(argv: list[str]) -> int: if "--out" not in argv: print(__doc__) return 1 split = argv.index("--out") sources = [Path(a) for a in argv[:split]] out = Path(argv[split + 1]) out.mkdir(parents=True, exist_ok=True) for index, source in enumerate(sources, start=1): name = source.stem.replace("shot-", "") prepare(source, out / f"play-screenshot-{index}-{name}.png") return 0 if __name__ == "__main__": raise SystemExit(main(sys.argv[1:]))