import zipfile from fastapi import FastAPI, UploadFile, File, Form from fastapi.responses import HTMLResponse, FileResponse from PIL import Image import io, math, json, os app = FastAPI() BASE = os.getcwd() OUTPUT_DIR = os.path.join(BASE, 'output') os.makedirs(OUTPUT_DIR, exist_ok=True) HTML = '''

Sprite Picker

Total Selected

0
WH:
Out WH:
Cols:
''' @app.get('/', response_class=HTMLResponse) def home(): return HTML @app.post('/export_picker') async def export_picker( file: UploadFile = File(...), outCols: int = Form(...), outWH: int = Form(...), # 新增參數 name: str = Form(...), picks: str = Form(...) ): data = await file.read() img = Image.open(io.BytesIO(data)).convert('RGBA') pick_list = json.loads(picks) if not pick_list: return HTMLResponse('None', status_code=400) # 輸出尺寸現在統一使用使用者設定的 outWH tw = th = outWH base_name = os.path.splitext(name)[0] num_picks = len(pick_list) num_images = num_picks // outCols if num_images == 0: return HTMLResponse('選取數量不足以構成一列', status_code=400) generated_files = [] for img_idx in range(num_images): # 建立畫布,寬度為 (OutWH * Cols),高度為 OutWH out_img = Image.new('RGBA', (outCols * tw, th), (0, 0, 0, 0)) for col_idx in range(outCols): p_idx = img_idx * outCols + col_idx p = pick_list[p_idx] box = (p['x'], p['y'], p['x'] + p['w'], p['y'] + p['h']) # 1. 裁切原始大小 tile = img.crop(box) # 2. 強制縮放至目標 OutWH # 使用 Resampling.LANCZOS 保持像素品質,若要保留像素感可用 NEAREST tile = tile.resize((tw, th), Image.Resampling.LANCZOS) # 3. 貼上 out_img.paste(tile, (col_idx * tw, 0)) file_path = os.path.join(OUTPUT_DIR, f"{base_name}_{img_idx+1}.png") out_img.save(file_path) generated_files.append(file_path) # 如果只有一張圖,直接回傳圖片 if len(generated_files) == 1: return FileResponse(generated_files[0], filename=f"{base_name}.png", media_type='image/png') # 如果有多張圖,打包成 ZIP zip_path = os.path.join(OUTPUT_DIR, f"{base_name}_batch.zip") with zipfile.ZipFile(zip_path, 'w') as zipf: for f in generated_files: zipf.write(f, os.path.basename(f)) return FileResponse(zip_path, filename=f"{base_name}.zip", media_type='application/zip') if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)