# 去除精灵白边：从外缘洪水填充，经"透明 OR 近白不透明"传播，把连通到外面的近白像素改透明。
# 内部白（被身体包住、连不到外面）保留。输出到新文件，不动原图。
# 用法: python _analysis/dehalo.py [输入png] [输出png] [白阈值(默认225)]
import sys
from collections import deque
from PIL import Image

src = sys.argv[1] if len(sys.argv) > 1 else 'project/materials/enemys.png'
dst = sys.argv[2] if len(sys.argv) > 2 else 'project/materials/enemys_dehalo.png'
WHITE = int(sys.argv[3]) if len(sys.argv) > 3 else 225  # min(r,g,b) >= 此值视为"近白"

im = Image.open(src).convert('RGBA')
W, H = im.size
px = im.load()

def transparent(x, y): return px[x, y][3] < 10
def nearwhite(x, y):
    r, g, b, a = px[x, y]
    return a >= 10 and r >= WHITE and g >= WHITE and b >= WHITE

# BFS 从所有边界像素出发；可经过 透明 或 近白 像素
visited = [[False] * W for _ in range(H)]
dq = deque()
for x in range(W):
    for y in (0, H - 1):
        if not visited[y][x] and (transparent(x, y) or nearwhite(x, y)):
            visited[y][x] = True; dq.append((x, y))
for y in range(H):
    for x in (0, W - 1):
        if not visited[y][x] and (transparent(x, y) or nearwhite(x, y)):
            visited[y][x] = True; dq.append((x, y))

removed = 0
while dq:
    x, y = dq.popleft()
    if nearwhite(x, y):  # 连通到外面的近白 → 抠成透明
        px[x, y] = (px[x, y][0], px[x, y][1], px[x, y][2], 0); removed += 1
    for dx, dy in ((1,0),(-1,0),(0,1),(0,-1)):
        nx, ny = x + dx, y + dy
        if 0 <= nx < W and 0 <= ny < H and not visited[ny][nx]:
            # 只从"背景"(透明/近白)继续扩散；遇到实色身体就停
            if transparent(nx, ny) or nearwhite(nx, ny):
                visited[ny][nx] = True; dq.append((nx, ny))

im.save(dst)
print('输入', src, im.size, '→ 输出', dst)
print('抠掉的白边像素:', removed, '(阈值 min(rgb)>=%d)' % WHITE)
