Tre scene con aree calpestabili e punti cliccabili ricavati dagli sfondi, tools/prepare_background.py per ridurli a 640x360, il castello del Trebbio che dà indizi in base ai progressi, container nginx sulla porta 8080. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
52 lines
2.1 KiB
Python
52 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Porta uno sfondo generato alla risoluzione del gioco (640x360, o il doppio in larghezza per le panoramiche).
|
|
|
|
python3 tools/prepare_background.py assets/raw/fortezza-esterno.png assets/scenes/fortezza-esterno.png \
|
|
--clone 625,332,12,12,-14,0
|
|
|
|
--crop x,y,w,h ritaglio nel file originale prima di ridurre (per immagini non in 16:9)
|
|
--clone x,y,w,h,dx,dy copia sopra il riquadro x,y,w,h i pixel spostati di dx,dy (coordinate finali):
|
|
serve a coprire filigrane o difetti con un pezzo di sfondo vicino; si può ripetere
|
|
--colors N riduce la tavolozza a N colori senza retinatura (0 = lascia i colori come sono)
|
|
"""
|
|
import argparse
|
|
from PIL import Image
|
|
|
|
|
|
def box(text, n):
|
|
values = [int(v) for v in text.split(',')]
|
|
if len(values) != n:
|
|
raise argparse.ArgumentTypeError(f'servono {n} numeri separati da virgola')
|
|
return values
|
|
|
|
|
|
def main():
|
|
p = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
p.add_argument('src')
|
|
p.add_argument('dst')
|
|
p.add_argument('--size', default='640x360')
|
|
p.add_argument('--crop', type=lambda t: box(t, 4))
|
|
p.add_argument('--clone', type=lambda t: box(t, 6), action='append', default=[])
|
|
p.add_argument('--colors', type=int, default=0)
|
|
a = p.parse_args()
|
|
|
|
w, h = (int(v) for v in a.size.split('x'))
|
|
im = Image.open(a.src).convert('RGB')
|
|
if a.crop:
|
|
x, y, cw, ch = a.crop
|
|
im = im.crop((x, y, x + cw, y + ch))
|
|
if abs(im.width / im.height - w / h) > 0.02:
|
|
raise SystemExit(f'proporzioni {im.width}x{im.height} diverse da {w}x{h}: usa --crop')
|
|
# BOX fa la media dei pixel di ogni blocco: niente aloni e niente sfocatura in più.
|
|
im = im.resize((w, h), Image.BOX)
|
|
for x, y, cw, ch, dx, dy in a.clone:
|
|
im.paste(im.crop((x + dx, y + dy, x + dx + cw, y + dy + ch)), (x, y))
|
|
if a.colors:
|
|
im = im.quantize(a.colors, dither=Image.Dither.NONE).convert('RGB')
|
|
im.save(a.dst, optimize=True)
|
|
print(f'{a.dst}: {w}x{h}')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|