Skip to main content
Glama
README.md
# PixelForge MCP

AI 생성 일러스트를 **인게임 도트 스프라이트로 변환**하는 파이프라인을 [MCP](https://modelcontextprotocol.io)(Model Context Protocol) 서버로 노출한 도구입니다. Claude·Cursor 같은 AI 에이전트가 Tool-use 로 직접 호출해, 배경제거 → 픽셀화 → 팔레트 통일 → 아웃라인 → 스프라이트시트 패킹을 자동화합니다.

여러 게임/앱 프로젝트에서 손으로 반복하던 "AI 일러 → 도트 스프라이트" 작업을 재사용 가능한 MCP 툴로 코드화한 것입니다. 아트 파이프라인 자동화 = TA(테크니컬 아트) 업무의 핵심 반복작업입니다.

![before / after](examples/sample/before_after.png)

*왼쪽부터: 입력 일러스트(1024px) · 32px 스프라이트 · 64px 스프라이트+selout 아웃라인 · 2프레임 스프라이트시트. 전부 동일 배율 nearest 업스케일. `uv run python examples/demo.py` 로 재생성.*

### 스튜디오 워크플로우: 캐릭터셋을 잠긴 공통 팔레트로 통일

![palette workflow](examples/sample/palette_workflow.png)

*위 = 캐릭터별 독립 팔레트(제각각) · 아래 = 잠긴 20색 공통 팔레트로 통일(인덱스 PNG 출력) · 맨 아래 = Aseprite 로 임포트되는 실제 `.gpl` 팔레트. `build_palette` 로 키아트에서 프로젝트 팔레트를 뽑아 `batch_pixelize` 에 넘기면 모든 에셋이 정확히 같은 색을 공유한다. 아트 코히어런스 = TA 자동화의 실제 가치. `uv run python examples/palette_workflow.py` 로 재생성.*

### 애니메이션 — 컷아웃 스켈레탈 리깅 (진짜 프레임 애니)

<p>
  <img src="examples/sample/anim_humanoid_walk.gif" width="150" alt="walk cycle">
  <img src="examples/sample/anim_humanoid_run.gif" width="150" alt="run cycle">
  <img src="examples/sample/anim_humanoid_punch.gif" width="150" alt="punch">
</p>

*캐릭터를 파트(몸통·머리·상완·하완·허벅지·정강이)로 나눠 부모-자식 관절 트리(FK)에 붙이고, 관절 회전을 키프레임으로 돌려 **프레임마다 서로 다른 포즈**를 합성한다 — Spine/DragonBones/Godot Cutout 방식. 2관절 팔다리라 **무릎·팔꿈치가 굽는 진짜 gait**(걷기·달리기·펀치). 한 장을 흔드는 워프가 아님. 결정적·오프라인. `uv run python examples/rig_demo.py` 로 재생성.*

**리그 킷(계약서) — 리깅용 아트를 규격에 맞게 뽑기.** 사후에 완성 스프라이트를 자르는 건 항상 타협이라, 처음부터 리깅용으로 그리는 게 정답. `export_rig_kit` 은 **배치 가이드 + 파츠별 생성 프롬프트 + rig.json** 을 뱉는다. 아티스트/AI 가 이 규격(슬롯·크기·피벗)에 맞춰 아트만 그리거나 생성해 PNG 를 교체하면 `animate_rig` 이 walk/run/idle/punch 를 자동 렌더한다.

<img src="examples/sample/rig_kit_guide.png" width="220" alt="rig layout guide">

*배치 가이드: 각 파츠 슬롯의 위치·크기 + 피벗(빨간 점). 이 규격대로 그리면 리그가 자동으로 물린다.*

**프레임 조립** — 포즈 프레임이 이미 있으면(아티스트·AI 생성) `assemble_animation` 이 N 프레임을 공통 스케일·단일 팔레트로 맞춰(깜빡임 방지) 스프라이트시트+타이밍JSON+GIF 로 조립한다. `pixelize=False` 면 이미 도트인 프레임을 색 보존해 팩만.

**절차적 juice**(보조) — `animate` 는 정적 스프라이트 한 장에 결정적 변형(bob/breathe/sway/hop/pulse)을 얹어 가벼운 idle 움직임을 만든다. 진짜 캐릭터 애니가 아니라 살아있는 느낌용 보조 툴.

## 왜 MCP 인가

같은 PIL 스크립트를 매번 복붙하는 대신 MCP 서버로 만들면, AI 에이전트가 **대화 중에 직접** "이 일러스트 64px 도트로 만들고, 프로젝트 팔레트로 통일해서 8프레임 시트로 묶어줘" 같은 요청을 툴 호출로 수행합니다. 에이전트 워크플로우 안에서 아트 파이프라인이 한 단계로 흡수됩니다.

## 품질이 어디서 나오나 (naive resize 와의 차이)

픽셀화의 품질은 다운스케일을 어떻게 하느냐에서 갈립니다. `img.resize()` 한 줄로는 색이 탁해지고 가장자리에 검은 띠가 낍니다. PixelForge 는:

- **감마보정 선형광 다운스케일** — sRGB 를 선형광으로 디코드한 뒤 리샘플. sRGB 값을 그대로 평균하면 색이 어두워지고 머디해지는 문제를 제거.
- **프리멀티플라이 알파 리샘플** — 투명 영역이 피사체 가장자리 색을 오염시키지 않게, 알파를 곱한 뒤 리샘플하고 나눠서 복원.
- **OKLab k-means 팔레트** — MEDIANCUT/FASTOCTREE 보다 지각적으로 정확한 팔레트. 색 램프(shadow→mid→highlight)가 뚜렷해져 '축소한 일러'가 아니라 '도트 스프라이트'로 읽힌다. (테스트로 median-cut 대비 OKLab 오차가 낮음을 검증)
- **실루엣 정리** — 리샘플이 남기는 튀는 픽셀·가시·1px 구멍을 despeckle/hole-fill 로 제거. 깨끗한 실루엣이 픽셀아트의 핵심.
- **하드 알파 + selout 아웃라인** — 반투명 가장자리는 칼같이. selout(선택적 아웃라인)은 각 테두리 픽셀을 맞닿은 실루엣 색을 어둡게(OKLab 명도만 낮춤) 칠해, 균일 검정보다 훨씬 프로다운 결과를 낸다.
- **Bayer 정렬 디더(옵션)** — 필요 시 밴딩을 규칙적 패턴으로 완화. FS 오차확산 같은 컨페티가 아니라 의도된 디더. 스프라이트 스케일에선 보통 off.
- **OKLab 팔레트 스냅** — 큐레이션/추출 팔레트로 여러 에셋을 통일(코히어런스). OKLab 거리라 색상 드리프트 없음.

## 스튜디오 연동

실제 도트 스튜디오 파이프라인(Aseprite·게임 엔진)에 그대로 들어가도록:

- **인덱스 컬러 PNG 출력**(`indexed=True`) — 픽셀아트 표준 형식. Aseprite 에서 바로 열어 편집·팔레트 스왑 가능, 용량 작음, 인덱스 0 = 투명.
- **팔레트 파일 export** — `.gpl`(GIMP/Aseprite)·`.hex`(lospec)·스와치 PNG.
- **잠긴 공통 팔레트**(`build_palette` → `palette=` 인자) — 캐릭터 키아트에서 프로젝트 팔레트를 뽑아 전체 에셋셋에 강제. 수백 개 에셋의 색 일관성을 자동 유지.
- **스프라이트시트 + JSON 메타데이터** — 프레임 좌표를 엔진 임포트용으로 함께 출력.

## 제공 툴 (18종)

| 툴 | 하는 일 |
|---|---|
| `pixelize` | 일러 → 고품질 도트 스프라이트 (감마보정 다운스케일 + OKLab k-means + 실루엣 정리 + selout 아웃라인, 옵션: 팔레트 잠금·인덱스 PNG·업스케일) |
| `animate_rig` | **컷아웃 스켈레탈 리그로 진짜 프레임 애니** (걷기/공격 등 실제 팔다리 움직임) → 프레임+시트+타이밍JSON+GIF |
| `create_demo_rig` | 빌트인 2족 리그(파트+스켈레톤+walk/idle/wave)를 저장 (저작 시작 템플릿) |
| `export_rig_kit` | **리깅용 아트 제작 킷** — 배치 가이드 + 파츠 생성 프롬프트 + rig.json (규격에 맞춰 아트만 뽑으면 리그 자동) |
| `assemble_animation` | 여러 포즈 프레임 → 공유 팔레트·공통 스케일로 애니 조립 (시트+GIF) |
| `animate` | 정적 스프라이트에 절차적 juice (bob/breathe/sway/hop/pulse) — idle 보조용 |
| `list_motions` | 절차적 juice 모션 목록/설명 |
| `pixelize_pair` | 2프레임 애니를 **공통 스케일·공유 팔레트**로 함께 도트화 (깜빡임 방지) |
| `remove_background` | 네 모서리 flood fill 로 단색/오프화이트 배경 투명화 (배경제거 모델 폴백) |
| `autocrop` | 투명 여백을 잘라 피사체만 남김 |
| `build_spritesheet` | 여러 프레임을 균일 격자 시트로 패킹 + **프레임 좌표 JSON**(엔진 임포트용) |
| `build_palette` | 여러 키아트에서 잠긴 공통 팔레트 생성 → `.gpl`/`.hex` (프로젝트 색 통일용) |
| `export_palette` | 단일 이미지 팔레트를 `.gpl`/`.hex` 로 추출 (Aseprite 임포트) |
| `quantize_palette` | 해상도 유지한 채 색 수만 축소 |
| `extract_palette` | 이미지에서 대표 팔레트(헥스) 추출 + 스와치 PNG |
| `snap_to_palette` | 큐레이션 팔레트로 스냅 (아트 코히어런스) |
| `list_palettes` | 내장 팔레트 목록 (pico8 / sweetie16 / db16 / edg32) |
| `batch_pixelize` | 폴더 전체를 동일/잠긴 팔레트로 일괄 픽셀화 (인덱스 PNG 지원) |

## 설치 & 실행

```bash
uv sync                 # 의존성 설치 (mcp, pillow, numpy)
uv run --extra dev pytest -q   # 테스트 38종
uv run pixelforge-mcp   # MCP 서버 실행 (stdio)
```

### Claude Desktop / Claude Code 에 등록

```json
{
  "mcpServers": {
    "pixelforge": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/pixelforge-mcp", "run", "pixelforge-mcp"]
    }
  }
}
```

등록 후:

> `~/art/dragon.png` 배경 제거하고 56px 도트로 만들어줘. 아웃라인 넣고, idle 프레임 `dragon_b.png` 도 같이 페어로 도트화해서 스프라이트시트 + 메타데이터로 묶어줘.

에이전트가 `remove_background` → `pixelize_pair` → `build_spritesheet` 를 순서대로 호출합니다.

## 설계

- `color.py` — 색 공간/리샘플링 코어 (감마, 프리멀티플라이 리샘플, OKLab, k-means 양자화, 실루엣 정리, selout 아웃라인, 팔레트 추출/스냅). 품질의 핵심.
- `palettes.py` — 큐레이션 레트로 팔레트 (PICO-8 / Sweetie16 / DB16 / EDG32).
- `export.py` — 인덱스 PNG / `.gpl` / `.hex` / 스와치 export, 팔레트 스펙 해석.
- `rig.py` — 컷아웃 스켈레탈 애니 엔진(FK 관절 트리 + 키프레임 + 파트 회전 합성) + 빌트인 템플릿(2관절 휴머노이드/단순 2족) + 배치 가이드·프롬프트 생성.
- `animate.py` — 절차적 juice 리그(bob/breathe/sway/wave/hop/pulse) + 루프 GIF 렌더.
- `pipeline.py` — 위를 조합한 **순수 함수** (MCP 비의존, 단위 테스트 대상).
- `server.py` — FastMCP 로 파이프라인을 툴로 노출하는 얇은 래퍼.

코어/파이프라인/서버 분리 덕분에 MCP 런타임 없이 직접 실행·테스트할 수 있고, CLI·CI 에서도 재사용됩니다. 테스트 38종(색 왕복, k-means vs median-cut 오차, 실루엣 정리, 인덱스 PNG 왕복, 잠긴 팔레트 배치 일관성, 애니 프레임/GIF/타이밍, 컷아웃 2관절 워크/런 등)으로 커버.

## 라이선스

MIT. 내장 팔레트는 각 커뮤니티 표준(퍼블릭/CC0).

TDQS

A3.9/5.0

Scored across 18 tools

Disambiguation4/5

Most tools have distinct purposes, but export_palette and extract_palette are very similar in functionality (both extract palette from a single image), which could cause confusion. The other tools are clearly differentiated by description and naming.

Naming Consistency5/5

All tool names use underscore_case and follow a verb-based pattern (e.g., pixelize, build_palette, list_motions). The naming is uniform and predictable, with no problematic mixing of styles.

Tool Count4/5

With 18 tools for pixel art creation and animation, the count is slightly above the ideal range but still reasonable. The tools cover the main workflow without being overwhelming.

Completeness5/5

The tool set covers the full pixel art pipeline: image preparation, pixelization, palette management, animation (procedural and rig-based), spritesheet packing, and batch processing. No obvious gaps for the intended domain.

Maintenance

ActivityInactive
ResponsivenessNo issues