Files
Matteo Benedetto 2703c28c96 Shogo: Mobile Armor Division (Linux Demo) — Flatpak
- Manifest multiarch i386 (Compat.i386 + GL32 + gamescope)
- Wrapper launcher con EULA dialog GTK3 (persistente), audio PipeWire, saves
- sdl12-compat build i386, risoluzione 1024x768@16, 60fps
- Icona composita (mech + kanji + banner SHOGO, trasparente) 512/256
- icon-build.py (post-processing rembg)
- Cartella flathub-submission pronta per la PR
- install-shogo-demo.sh per PC nuovi
2026-08-19 22:16:42 +02:00

83 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""Icona Shogo v2: rimozione sfondo con rembg (U2Net) + composizione kanji/mech/banner.
Uso: PYTHONPATH=~/.local/pylibs-rembg python3 icon-build.py
"""
import sys
sys.path.insert(0, '/home/enne2/.local/pylibs-rembg')
from PIL import Image, ImageFilter
from rembg import remove
D = '/home/enne2/Dev/shogo-demo-flatpak'
SRC_MECH = f'{D}/shogo_game_icon_1787156055996.jpg'
SRC_BANNER = f'{D}/shogo_logo_banner_1787156448853.jpg'
# ---------- 1) mech: rimozione sfondo con rembg ----------
print('rembg: rimozione sfondo mech (può richiedere un paio di minuti su CPU)...')
with open(SRC_MECH, 'rb') as f:
inp = f.read()
out = remove(inp)
mech = Image.open(__import__('io').BytesIO(out)).convert('RGBA')
# pulizia: rimuovi eventuali pixel semitrasparenti isolati (opening della maschera alpha)
a = mech.split()[3].point(lambda v: 0 if v < 40 else 255)
mech.putalpha(a)
mech.save(f'{D}/icon-mech-alpha.png')
print('mech alpha:', mech.size)
# ---------- 2) kanji: estrazione dei pixel rosso-scuro (fondale) ----------
src = Image.open(SRC_MECH).convert('RGBA')
px = src.load()
W, H = src.size
kanji = Image.new('RGBA', (W, H), (0, 0, 0, 0))
kp = kanji.load()
for y in range(H):
for x in range(W):
r, g, b, a = px[x, y]
# rosso scuro del kanji: r dominante ma scuro, senza essere arancione acceso del mech
if r > 55 and r < 175 and r > g + 25 and r > b + 25 and a > 100:
kp[x, y] = (r, g, b, 255)
kanji.save(f'{D}/icon-kanji.png')
print('kanji estratto')
# ---------- 3) banner: estrazione e pulizia bordi ----------
bim = Image.open(SRC_BANNER).convert('RGBA')
bp = bim.load()
bw, bh = bim.size
xs, ys = [], []
for y in range(bh):
for x in range(bw):
r, g, b = bp[x, y][:3]
if (r + g + b) / 3 > 40:
xs.append(x); ys.append(y)
x0, x1, y0, y1 = max(0, min(xs)-14), min(bw-1, max(xs)+14), max(0, min(ys)-14), min(bh-1, max(ys)+14)
banner = bim.crop((x0, y0, x1+1, y1+1)).copy()
b2 = banner.load()
bw2, bh2 = banner.size
for y in range(bh2):
for x in range(bw2):
r, g, b = b2[x, y][:3]
if (r + g + b) / 3 <= 40:
b2[x, y] = (0, 0, 0, 0)
# erosione leggera dell'alpha per togliere l'alone
alpha = banner.split()[3].filter(ImageFilter.MinFilter(3))
banner.putalpha(alpha)
banner.save(f'{D}/icon-banner2.png')
print('banner:', banner.size)
# ---------- 4) composizione ----------
C = 1024
canvas = Image.new('RGBA', (C, C), (0, 0, 0, 0))
# kanji dietro, grande, opacità ~28%
k2 = kanji.resize((int(C*0.95), int(C*0.95)), Image.LANCZOS)
k2.putalpha(k2.split()[3].point(lambda v: int(v * 0.28)))
canvas.alpha_composite(k2, ((C-k2.width)//2, (C-k2.height)//2 - int(C*0.02)))
# mech sopra
m = mech.resize((C, C), Image.LANCZOS)
canvas.alpha_composite(m, (0, 0))
# banner in basso
bw3 = int(C * 0.60)
bh3 = int(banner.height * (bw3 / banner.width))
b3 = banner.resize((bw3, bh3), Image.LANCZOS)
canvas.alpha_composite(b3, ((C-bw3)//2, C - bh3 - int(C*0.035)))
canvas.save(f'{D}/icon-final2.png')
print('composta: icon-final2.png', canvas.size)