diff --git a/README.md b/README.md index 59655d0..a61e3fa 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ SpriteTool 是一個整合式的 Web 應用程式,集合了四個專業級工 - **即時預覽** - 調整 threshold 時實時顯示去底色效果 - **預覽底色檢查** - 可修改預覽背景顏色以檢查邊界精度(純檢查用,不影響導出) - **內縮虛線框** - 在預覽上顯示每個格子的內縮邊界(粉紅色虛線框),視覺化檢查內縮效果 +- **座標偏移** - 支援 X/Y 軸偏移調整,處理不對齊的網格 - **智慧裁切** - 根據行列數和內縮距離精確分割每格 - **縮放還原** - 內縮後自動放大回原格尺寸 - **批量輸出** - 導出個別格子 PNG + 組合完整圖 @@ -102,6 +103,19 @@ SpriteTool 是一個整合式的 Web 應用程式,集合了四個專業級工 --- +### 📦 Sprite Splitter(精靈分割器) +最基礎的圖片分割工具,將 Sprite Sheet 按網格切開並打包。 + +**功能特性:** +- 根據行列數自動計算格子大小 +- 實時顯示分割線預覽 +- 一鍵將所有格子打包為 ZIP 下載 +- 支援像素藝術縮放顯示(保持銳利) + +**使用場景:** 快速拆解素材包、動畫序列導出 + +--- + ## 🚀 快速開始 ### 環境需求 @@ -133,6 +147,7 @@ python tool.py - **Sprite Flipper**: `http://localhost:8000/flipper/` - **Sprite Merger**: `http://localhost:8000/merger/` - **Inset Crop Tool**: `http://localhost:8000/inset/` +- **Sprite Splitter**: `http://localhost:8000/splitter/` --- @@ -148,6 +163,7 @@ SpriteTool/ ├── rotate.py # Flipper 核心處理邏輯 ├── sprite_merger.py # Sprite Merger 子應用 ├── inset_crop_tool.py # Inset Crop Tool 子應用 +├── sprite_splitter.py # Sprite Splitter 子應用 ├── remove_pink_background.py # 色彩去除工具(獨立使用) ├── output/ # Grid Tool 導出目錄 ├── shiny_output/ # Shiny Maker 導出目錄 @@ -215,6 +231,7 @@ SpriteTool/ - 確認去底色效果滿意 3. **設定裁切參數** - 輸入圖片的行列數(Cols/Rows) + - 調整 **X/Y Offset** 偏移量以對齊網格 - 設定四邊內縮距離(px) - 查看計算的格子尺寸及輸出數量 4. **確認並下載** @@ -222,6 +239,12 @@ SpriteTool/ - 系統執行去底色 → 內縮裁切 → 放大還原 - 下載包含所有格子 PNG + 完整組合圖的 ZIP 檔 +### Sprite Splitter 工作流 + +1. **上傳圖片** - 選擇要分割的 Sprite Sheet +2. **設定網格** - 輸入行列數,預覽圖會即時顯示藍色分割線 +3. **下載** - 點擊「下載 ZIP」取得所有格子檔案 + --- ## 🛠️ 技術架構 @@ -275,6 +298,10 @@ SpriteTool/ - `POST /inset/preview` - 即時預覽去底色效果 - `POST /inset/process` - 執行去底色 + 裁切 + 打包 +### Sprite Splitter +- `GET /splitter/` - 首頁 +- `POST /splitter/process` - 執行圖片網格分割並打包 + --- ## 🎨 UI/UX 特性 @@ -337,4 +364,4 @@ SpriteTool/ --- **最後更新**: 2026 年 5 月 -**版本**: 1.2.0 +**版本**: 1.3.0 diff --git a/README_EN.md b/README_EN.md index f8fd7aa..8015c33 100644 --- a/README_EN.md +++ b/README_EN.md @@ -91,6 +91,7 @@ Remove Chroma Key background and perform intelligent inset cropping and enlargem - **Real-time Preview** - Instantly view background removal effects while adjusting threshold. - **Preview Background Customization** - Change preview background color to check edge precision (inspection only, does not affect export). - **Inset Guide Lines** - Display dashed lines showing each cell's inset boundary (pink dashed outline) for visual verification of inset effects. +- **Coordinate Offset** - Support for X/Y axis offset adjustment to handle misaligned grids. - **Smart Cropping** - Precisely divide cells based on rows/columns and inset distance. - **Enlarge After Crop** - Automatically enlarge back to original cell size after inset cropping. - **Batch Export** - Export individual cell PNGs + combined full image. @@ -100,6 +101,19 @@ Remove Chroma Key background and perform intelligent inset cropping and enlargem --- +### 📦 Sprite Splitter +The simplest tool to split a Sprite Sheet into grid cells and package them into a ZIP file. + +**Key Features:** +- Automatically calculates cell size based on row and column counts. +- Real-time preview of grid split lines. +- One-click packaging of all cells into a ZIP archive for download. +- Pixel-art optimized rendering (maintains sharpness). + +**Use Cases:** Quick decomposition of asset packs, animation sequence export. + +--- + ## 🚀 Quick Start ### Prerequisites @@ -131,6 +145,7 @@ Visit the home page to see all available tools, or access them directly: - **Sprite Flipper**: `http://localhost:8000/flipper/` - **Sprite Merger**: `http://localhost:8000/merger/` - **Inset Crop Tool**: `http://localhost:8000/inset/` +- **Sprite Splitter**: `http://localhost:8000/splitter/` ## 📂 Project Structure @@ -144,6 +159,7 @@ SpriteTool/ ├── rotate.py # Flipper core processing logic ├── sprite_merger.py # Sprite Merger sub-app ├── inset_crop_tool.py # Inset Crop Tool sub-app +├── sprite_splitter.py # Sprite Splitter sub-app ├── remove_pink_background.py # Color removal tool (standalone use) ├── output/ # Grid Tool export directory ├── shiny_output/ # Shiny Maker export directory @@ -211,6 +227,7 @@ SpriteTool/ - Confirm the background removal result. 3. **Configure Crop Parameters** - Enter grid row and column counts (Cols/Rows). + - Adjust **X/Y Offset** to align the grid correctly. - Set inset distance (px) for all edges. - View calculated cell size and output count. 4. **Confirm and Download** @@ -218,6 +235,12 @@ SpriteTool/ - System executes: Remove background → Inset crop → Enlarge back → Package. - Download ZIP containing all individual cell PNGs + combined image. +### Sprite Splitter Workflow + +1. **Upload Image** - Select the Sprite Sheet to split. +2. **Set Grid** - Enter row and column counts; the preview will show blue split lines instantly. +3. **Download** - Click "Download ZIP" to get all individual cell files. + --- ## 🛠️ Technical Architecture @@ -270,6 +293,10 @@ SpriteTool/ - `GET /inset/` - Home page. - `POST /inset/preview` - Real-time background removal preview. - `POST /inset/process` - Execute background removal + cropping + packaging. + +### Sprite Splitter +- `GET /splitter/` - Home page. +- `POST /splitter/process` - Execute grid splitting and packaging. --- ## 🎨 UI/UX Features @@ -332,4 +359,4 @@ Issues and Pull Requests are welcome! --- **Last Updated**: May 2026 -**Version**: 1.2.0 +**Version**: 1.3.0 diff --git a/inset_crop_tool.py b/inset_crop_tool.py index 4dae0b4..b212ee4 100644 --- a/inset_crop_tool.py +++ b/inset_crop_tool.py @@ -147,12 +147,12 @@ HTML = """ -
+
-
+

裁切設定

-
+
+
+ + +
+
+ + +
-
+
+
+
+ + + + +
+ + +
+

預覽(分割線)

+
+ + +

尚未上傳圖片

+
+
+ +
+ + + + +""" + + +@app.get("/", response_class=HTMLResponse) +async def index(): + return HTML + + +@app.post("/process") +async def process( + file: UploadFile = File(...), + cols: int = Form(...), + rows: int = Form(...), +): + """分割圖片並打包為 ZIP。""" + raw = await file.read() + try: + src = Image.open(io.BytesIO(raw)) + src = src.convert("RGBA") + except Exception as e: + return PlainTextResponse(f"圖片載入失敗:{str(e)}", status_code=400) + + W, H = src.size + tile_w = W // cols + tile_h = H // rows + + tiles: list[Image.Image] = [] + for r in range(rows): + for c in range(cols): + x0, y0 = c * tile_w, r * tile_h + cropped = src.crop((x0, y0, x0 + tile_w, y0 + tile_h)) + tiles.append(cropped) + + buf = io.BytesIO() + with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf: + for idx, tile in enumerate(tiles): + r, c = divmod(idx, cols) + tb = io.BytesIO() + tile.save(tb, format="PNG") + zf.writestr(f"tile_r{r:02d}_c{c:02d}.png", tb.getvalue()) + + buf.seek(0) + return StreamingResponse( + buf, + media_type="application/zip", + headers={"Content-Disposition": "attachment; filename=sprite_split.zip"}, + ) + + +if __name__ == "__main__": + import uvicorn + uvicorn.run("sprite_splitter:app", host="0.0.0.0", port=8004, reload=True) diff --git a/tool.py b/tool.py index 3acbc8f..ba7653b 100644 --- a/tool.py +++ b/tool.py @@ -11,6 +11,7 @@ from shiny_maker import app as shiny_app from rotate_webtool import app as flipper_app from sprite_merger import app as merger_app from inset_crop_tool import app as inset_app +from sprite_splitter import app as splitter_app app = FastAPI(title="Game Dev Suite") @@ -25,6 +26,7 @@ NAVBAR_HTML = """ 🔄 Flipper 🧩 Merger ✂️ Inset Crop + 📦 Splitter """ @@ -57,6 +59,7 @@ app.mount("/shiny", shiny_app) app.mount("/flipper", flipper_app) app.mount("/merger", merger_app) app.mount("/inset", inset_app) +app.mount("/splitter", splitter_app) # 首頁入口 @app.get("/", response_class=HTMLResponse) @@ -79,6 +82,7 @@ async def index(): 🔄 Flipper 🧩 Merger ✂️ Inset Crop + 📦 Splitter