diff --git a/_grassland.png b/_grassland.png
new file mode 100644
index 0000000..216bfa6
Binary files /dev/null and b/_grassland.png differ
diff --git a/fireant.png b/fireant.png
new file mode 100644
index 0000000..5645a7c
Binary files /dev/null and b/fireant.png differ
diff --git a/grassland.png b/grassland.png
new file mode 100644
index 0000000..8b96763
Binary files /dev/null and b/grassland.png differ
diff --git a/sprite_merger.py b/sprite_merger.py
new file mode 100644
index 0000000..629ce24
--- /dev/null
+++ b/sprite_merger.py
@@ -0,0 +1,158 @@
+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}"'},
+ )
diff --git a/tool.py b/tool.py
index d2d333e..c3407c1 100644
--- a/tool.py
+++ b/tool.py
@@ -9,6 +9,7 @@ from sprite_tool_fullstack import app as grid_app
from sprite_webtool import app as picker_app
from shiny_maker import app as shiny_app
from rotate_webtool import app as flipper_app
+from sprite_merger import app as merger_app
app = FastAPI(title="Game Dev Suite")
@@ -21,6 +22,7 @@ NAVBAR_HTML = """
🎯 Picker Tool
✨ Shiny Maker
🔄 Flipper
+ 🧩 Merger
"""
@@ -55,6 +57,7 @@ app.mount("/grid", grid_app)
app.mount("/picker", picker_app)
app.mount("/shiny", shiny_app)
app.mount("/flipper", flipper_app)
+app.mount("/merger", merger_app)
# 首頁入口
@app.get("/", response_class=HTMLResponse)
@@ -76,6 +79,7 @@ async def index():
🎯 Picker Tool
✨ Shiny Maker
🔄 Flipper
+ 🧩 Merger