Le nuvole che scorrono sono quelle disegnate da Codex nello stile degli sfondi (tools/ritaglia_sprite.py)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ApqNBvNbNCwXqR2RLo8QJh
This commit is contained in:
2026-10-24 23:56:07 +02:00
co-authored by Claude Opus 5.5
parent fd0fddae5d
commit a9528f7ed7
12 changed files with 57 additions and 32 deletions
+43
View File
@@ -0,0 +1,43 @@
"""Ritaglia un foglio di sprite su fondo magenta pieno (#ff00ff) nei suoi pezzi separati: ogni macchia (con i suoi
pixel staccati vicini) diventa un PNG trasparente, rimpicciolito di SCALA, in ordine da sinistra a destra e
dall'alto in basso.
python3 tools/ritaglia_sprite.py assets/generated/nuvole.png assets/effects/nuvola 0.24"""
import sys
from PIL import Image, ImageFilter
src, prefix, scale = sys.argv[1], sys.argv[2], float(sys.argv[3])
im = Image.open(src).convert('RGBA')
px = im.load()
W, H = im.size
for y in range(H):
for x in range(W):
r, g, b, a = px[x, y]
if r > 200 and g < 90 and b > 200: px[x, y] = (0, 0, 0, 0)
# Le macchie: si uniscono i pixel vicini (dilatando l'alfa) e si cercano i pezzi connessi.
mask = im.getchannel('A').point(lambda v: 255 if v else 0).filter(ImageFilter.MaxFilter(15))
m = mask.load()
seen = [[False] * W for _ in range(H)]
boxes = []
for y in range(0, H, 2):
for x in range(0, W, 2):
if m[x, y] and not seen[y][x]:
stack, l, t, r, b = [(x, y)], x, y, x, y
seen[y][x] = True
while stack:
cx, cy = stack.pop()
l, t, r, b = min(l, cx), min(t, cy), max(r, cx), max(b, cy)
for nx, ny in ((cx + 1, cy), (cx - 1, cy), (cx, cy + 1), (cx, cy - 1)):
if 0 <= nx < W and 0 <= ny < H and not seen[ny][nx] and m[nx, ny]:
seen[ny][nx] = True
stack.append((nx, ny))
if (r - l) * (b - t) > 400: boxes.append((l, t, r + 1, b + 1))
boxes.sort(key=lambda bx: (bx[1] // 150, bx[0]))
for i, bx in enumerate(boxes, 1):
piece = im.crop(bx)
piece = piece.crop(piece.getbbox())
w, h = max(1, round(piece.width * scale)), max(1, round(piece.height * scale))
piece = piece.resize((w, h), Image.BOX)
a = piece.getchannel('A').point(lambda v: 255 if v > 110 else 0)
piece.putalpha(a)
piece.save(f'{prefix}-{i}.png')
print(f'{prefix}-{i}.png', w, h)