#!/usr/bin/env python3 """Gera o banners.png do Pixel Dungeon: Shattered Web (titulo proprio, no lugar do logo do Shattered Pixel Dungeon). Uso: make-banners.py Mantem as faixas "Boss Slain" e "Game Over" do original (GPL-3, Evan Debenham) e redesenha so as quatro faixas do titulo (retrato, retrato com brilho, paisagem, paisagem com brilho). O texto usa a fonte pixel_font.ttf do jogo. """ import sys from PIL import Image, ImageDraw, ImageFont src, fontfile, out = sys.argv[1:4] im = Image.open(src).convert("RGBA") REGIONS = { # (x0, y0, x1, y1) "port": (0, 0, 139, 100), "port_glow": (139, 0, 278, 100), "land": (0, 100, 240, 157), "land_glow": (240, 100, 480, 157), } for box in REGIONS.values(): im.paste((0, 0, 0, 0), box) STONE = (131, 141, 110, 255) LIGHT = (213, 220, 200, 255) DARK = (15, 20, 8, 255) GLOW = (48, 147, 65) def text_mask(text, size, width): """Mascara 1-bit do texto, centralizada em 'width' (sem suavizacao).""" f = ImageFont.truetype(fontfile, size) probe = Image.new("L", (width * 2, size * 3), 0) d = ImageDraw.Draw(probe) d.fontmode = "1" d.text((0, 0), text, font=f, fill=255) bbox = probe.getbbox() glyphs = probe.crop(bbox).point(lambda v: 255 if v > 127 else 0) return glyphs def stamp(base, mask, cx, top): """Desenha a mascara com contorno escuro, face de pedra e luz na borda de cima.""" w, h = mask.size x = cx - w // 2 px = mask.load() layer = Image.new("RGBA", base.size, (0, 0, 0, 0)) lp = layer.load() # contorno e sombra for yy in range(h): for xx in range(w): if px[xx, yy]: for dx in (-1, 0, 1): for dy in (-1, 0, 1, 2): X, Y = x + xx + dx, top + yy + dy if 0 <= X < base.width and 0 <= Y < base.height: lp[X, Y] = DARK for yy in range(h): for xx in range(w): if px[xx, yy]: up = px[xx, yy - 1] if yy > 0 else 0 lp[x + xx, top + yy] = LIGHT if not up else STONE base.alpha_composite(layer) return w, h def glow(base, mask, cx, top): w, h = mask.size x = cx - w // 2 px = mask.load() bp = base.load() for yy in range(h): for xx in range(w): if px[xx, yy]: a = 255 if (xx * 3 + yy * 5) % 7 == 0 else 51 bp[x + xx, top + yy] = GLOW + (a,) def draw_title(box, glow_box, lines): x0, y0, x1, y1 = box w = x1 - x0 canvas = Image.new("RGBA", (w, y1 - y0), (0, 0, 0, 0)) gl = Image.new("RGBA", (glow_box[2] - glow_box[0], glow_box[3] - glow_box[1]), (0, 0, 0, 0)) for text, size, top in lines: m = text_mask(text, size, w) stamp(canvas, m, w // 2, top) glow(gl, m, w // 2, top) im.alpha_composite(canvas, (x0, y0)) im.alpha_composite(gl, (glow_box[0], glow_box[1])) # retrato 139x100: PIXEL / DUNGEON / SHATTERED WEB draw_title(REGIONS["port"], REGIONS["port_glow"], [("PIXEL", 30, 6), ("DUNGEON", 30, 38), ("SHATTERED WEB", 12, 78)]) # paisagem 240x57: PIXEL DUNGEON / SHATTERED WEB draw_title(REGIONS["land"], REGIONS["land_glow"], [("PIXEL DUNGEON", 30, 6), ("SHATTERED WEB", 12, 42)]) im.save(out, optimize=True)