tools/graphics.py (2598 bytes)
1 """Make the Chrome Web Store promo tiles in store/graphics/. 2 3 promo-440x280.png: the icon and the name. 4 marquee-1400x560.png: the icon, the name and a line of text, next to a store screenshot. 5 The screenshots come from tools/shots/ (see store/listing.md). 6 """ 7 import pathlib 8 from PIL import Image, ImageDraw, ImageFont 9 10 ROOT = pathlib.Path(__file__).resolve().parent.parent 11 OUT = ROOT / "store" / "graphics" 12 BG = (15, 15, 15) 13 FG = (240, 240, 240) 14 DIM = (170, 170, 170) 15 16 def font(size: int) -> ImageFont.ImageFont: 17 for name in ("segoeuib.ttf", "arialbd.ttf", "DejaVuSans-Bold.ttf"): 18 try: 19 return ImageFont.truetype(name, size) 20 except OSError: 21 pass 22 return ImageFont.load_default() 23 24 def icon(size: int) -> Image.Image: 25 return Image.open(ROOT / "icons" / "128.png").convert("RGBA").resize((size, size), Image.LANCZOS) 26 27 def promo() -> None: 28 canvas = Image.new("RGB", (440, 280), BG) 29 i = icon(128) 30 canvas.paste(i, ((440 - 128) // 2, 40), i) 31 draw = ImageDraw.Draw(canvas) 32 for text, size, y in (("SubRead", 36, 190), ("your subtitles on YouTube", 20, 236)): 33 f = font(size) 34 w = draw.textlength(text, font=f) 35 draw.text(((440 - w) / 2, y), text, font=f, fill=FG) 36 canvas.save(OUT / "promo-440x280.png") 37 38 def marquee() -> None: 39 canvas = Image.new("RGB", (1400, 560), BG) 40 # The right side: the video area of store/demo/marquee-frame.png. Screenshot 2 has the same frame, but its 41 # line is "He loved to dust his old grammars…" and its panel is open. Paste only the strip 42 # with that line over the line of that frame. 43 box = (110, 56, 1155, 686) 44 strip = (box[0], 570, box[2], 616) 45 shot = Image.open(ROOT / "store" / "demo" / "marquee-frame.png").convert("RGB").crop(box) 46 line = Image.open(OUT / "screenshot-2-moby-dick-panel.png").convert("RGB").crop(strip) 47 shot.paste(line, (0, strip[1] - box[1])) 48 shot = shot.resize((round(shot.width * 440 / shot.height), 440), Image.LANCZOS) 49 canvas.paste(shot, (1400 - shot.width - 40, (560 - shot.height) // 2)) 50 draw = ImageDraw.Draw(canvas) 51 i = icon(112) 52 canvas.paste(i, (64, 96), i) 53 draw.text((64, 236), "SubRead", font=font(72), fill=FG) 54 for n, line in enumerate(("Read along with audiobooks on YouTube,", "with subtitles made from the book itself.")): 55 draw.text((64, 336 + n * 40), line, font=font(28), fill=DIM) 56 canvas.save(OUT / "marquee-1400x560.png") 57 58 OUT.mkdir(parents=True, exist_ok=True) 59 promo() 60 marquee() 61 for p in sorted(OUT.iterdir()): 62 print(p.relative_to(ROOT), Image.open(p).size)