"""Read-only image analysis: find separate figures for reliable sprite slicing."""
from collections import deque
from pathlib import Path
import argparse
import json
from PIL import Image

parser=argparse.ArgumentParser()
parser.add_argument('source',type=Path)
parser.add_argument('--lua',type=Path,required=True)
parser.add_argument('--metadata',type=Path,required=True)
parser.add_argument('--rows',type=int,default=4)
parser.add_argument('--columns',type=int,default=3)
args=parser.parse_args()
image=Image.open(args.source).convert('RGBA')
width,height=image.size
mask=bytearray(1 if p>=192 else 0 for p in image.getchannel('A').tobytes())
components=[]
for start in range(width*height):
    if not mask[start]: continue
    mask[start]=0
    queue=deque([start])
    count=0
    x0,y0,x1,y1=width,height,-1,-1
    while queue:
        point=queue.popleft()
        y,x=divmod(point,width)
        count+=1
        x0,y0,x1,y1=min(x0,x),min(y0,y),max(x1,x),max(y1,y)
        for dx,dy in [(-1,0),(1,0),(0,-1),(0,1),(-1,-1),(1,-1),(-1,1),(1,1)]:
            xx,yy=x+dx,y+dy
            if 0<=xx<width and 0<=yy<height:
                neighbour=yy*width+xx
                if mask[neighbour]:
                    mask[neighbour]=0
                    queue.append(neighbour)
    if count>=300:
        components.append(dict(x=x0,y=y0,w=x1-x0+1,h=y1-y0+1,pixels=count))
count=args.rows*args.columns
figures=sorted(components,key=lambda b:b['pixels'],reverse=True)[:count]
assert len(figures)==count,(len(figures),count)
figures.sort(key=lambda b:b['y']+b['h']/2)
frames=[]
for row in range(args.rows):
    frames.extend(sorted(figures[row*args.columns:(row+1)*args.columns],key=lambda b:b['x']))
for box in frames:
    # Head alignment excludes the moving arms that widen a figure's overall box.
    head=image.getchannel('A').crop((box['x'],box['y'],box['x']+box['w'],box['y']+max(1,int(box['h']*.22)))).getbbox()
    box['head_x']=(head[0]+head[2])/2 if head else box['w']/2
args.metadata.write_text(json.dumps(dict(method='8-connected alpha >=192; largest figures sorted into rows',frames=frames),indent=2)+'\n')
args.lua.write_text('return {\n'+',\n'.join('{x=%d,y=%d,w=%d,h=%d,head_x=%.4f}'%(b['x'],b['y'],b['w'],b['h'],b['head_x']) for b in frames)+'\n}\n')
print(args.source.name,'isolated',len(frames),'figures')
