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:
@@ -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)
|
||||
Reference in New Issue
Block a user