import io import base64 from fastapi import FastAPI, UploadFile, File, Form from fastapi.responses import HTMLResponse, Response from PIL import Image app = FastAPI() HTML = """ Sprite Merger

🧩 Sprite Merger

將來源圖片 merge 進主圖的指定 tile 座標

""" @app.get("/", response_class=HTMLResponse) async def index(): return HTML @app.post("/merge") async def merge_sprites( main_image: UploadFile = File(...), source_image: UploadFile = File(...), main_cols: int = Form(...), main_rows: int = Form(...), target_col: int = Form(...), target_row: int = Form(...), output_name: str = Form("output.png"), ): main_data = await main_image.read() source_data = await source_image.read() main_img = Image.open(io.BytesIO(main_data)).convert("RGBA") source_img = Image.open(io.BytesIO(source_data)).convert("RGBA") main_w, main_h = main_img.size tile_w = main_w // main_cols tile_h = main_h // main_rows # 將來源圖縮放至 tile 尺寸 source_resized = source_img.resize((tile_w, tile_h), Image.NEAREST) paste_x = target_col * tile_w paste_y = target_row * tile_h result = main_img.copy() result.paste(source_resized, (paste_x, paste_y), source_resized) buf = io.BytesIO() result.save(buf, format="PNG") buf.seek(0) return Response( content=buf.read(), media_type="image/png", headers={"Content-Disposition": f'attachment; filename="{output_name}"'}, )