# Pixel Asset Gen

> ドット絵ワークスペース用のキャラクタースプライトを、codexのimage_genに指示して生成する手順。 承認済みシートを土台にしたidentity差し替え、10行の意味的一貫性、実画面プレビュー、 runtime反映前の承認までを扱う。Animaのpixel_sheet.pngを新規作成・差し替え・修復するとき、 Pixel Workspaceのキャラクターが細い、潰れる、行ごとに別人化する問題を直すときに使う。

- Skill: `xuiltul/pixel-asset-gen` (Agent Skill, multi-file: 7 files)
- Install (CLI): `npx skillmds@latest add xuiltul/pixel-asset-gen`
- Raw SKILL.md: https://api.skillmd.com/api/skills/xuiltul/pixel-asset-gen/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: xuiltul (https://skillmd.com/u/xuiltul)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/xuiltul/pixel-asset-gen

---


# Pixel アセット生成 — codexへの指示の出し方

ドット絵ワークスペース（`/app/workspace/pixel/`）のキャラクタースプライトを作る手順。
2026-07-29〜30にフリート全体で確立した方式を記録したもの。実プロンプト全文と後処理の詳細は同ディレクトリの `PIPELINE_reference.md` にある。

## 前提

- 画像生成は **codexの組み込み `image_gen`** で行う（grokには無い）。指示に「組み込みの
  image_gen ツールを使う。SVG/HTML/CSSでの代替は不可」と明記しないと、勝手にSVGで代替される
- スプライトは **384×960**（96×96フレーム × 4列 × 10行）、透過PNG、アルファ2値。
  行順は idle / working / thinking / talking / walk_down / walk_up / walk_side /
  sleeping / success / error（正本は `server/static/workspace/pixel/CONTRACT.md`）
- 実名アセットは**リポジトリに置かない**。配置先は `<data_dir>/animas/<name>/assets/pixel_sheet.png`
  （人間役は `<data_dir>/workspace_pixel/assets/chars/human.png`）

## 方式は2つあり、使い分ける

| 状況 | 方式 |
| --- | --- |
| 基準キャラを新しく作る（1体目・画風を決める） | ゼロから生成。1枚の種で画風の承認を取ってから10行に展開 |
| 2体目以降・フリートへ展開する | **承認済みシートを土台にした「キャラ差し替え」** |

**2体目以降を独立生成してはいけない。** キャラごとに顔の大きさがバラバラになり、
オフィスに並べた瞬間に不揃いだと分かる（フリート全体で実際に失敗して作り直した）。

## キャラ差し替え方式の手順（これが本題）

### 0. 正本とidentityを固定する

- 形状・ポーズ・ドット密度の正本は、現在承認済みのmio
  `~/.animaworks/animas/mio/assets/pixel_sheet.png` とする。開始時にSHA-256を記録する。
- 対象Animaの `assets/prompt.txt`、`avatar_chibi.png`、`avatar_bustup.png` を読み、
  髪型、髪色、瞳、髪飾り、服装を1つのidentity仕様へ確定する。
- 参照同士が矛盾する場合は多数一致と明示記述を優先し、解消できなければ生成前に人間へ確認する。
- identity仕様は10行40フレーム共通の不変条件である。状態によって髪丈、髪飾り、瞳、服装を変えない。

### 1. 土台を作る — ここが成否を分ける

承認済みシートを行ごとに切り出し、**全10行を例外なくPOINTで400%拡大し**、透明部分をマゼンタで埋めた
1536×384の画像**を編集対象にする。

```bash
magick <基準シートの行ストリップ>.png \
  -filter point -resize 400% \
  -background '#FF00FF' -alpha background -alpha remove -alpha off \
  <作業dir>/base_row0_idle_x4_magenta.png
```

384×96のまま渡すと**モデルが顔・髪・体型を再解釈する**。idleだけでなく全10行で必ず400%版を渡す。
過去のMei生成では後半行が低解像度入力へ戻り、行ごとに長髪とボブが混在したため、低解像度入力は不合格とする。

### 2. image_genへの指示

1行につき1回呼ぶ。入力画像はこの順で3枚:

1. 上で作った400%＋マゼンタの土台（＝編集対象）
2. そのキャラの `avatar_chibi.png`（全身・服装の同定）
3. そのキャラの `avatar_bustup.png`（顔・色の同定）

プロンプトは `precise-object-edit` 構成で書く。全文は `PIPELINE_reference.md` にあるが、要点は:

- Primary request: **Image 1 を編集する。キャラの同一性だけを差し替え、レイアウト・
  スケール・シルエット・アニメーション・ピクセルグリッドは Image 1 のまま**
- Composition: 4コマそれぞれの**ポーズ・向き・体の大きさ・肩幅・頭頂の高さ・
  露出した顔の大きさ・顔の中心・目鼻口の位置と間隔**を維持。**顔や頭を大きくするな**
- Constraints: 目・眉・鼻・口・頬は小さく分離した読み取れるドットの塊のまま。
  **顔（目・鼻・口・頬）に新しい暗色の点・影・輪郭・髪の毛・孤立ピクセルを重ねるな**。
  暗い髪は顔の境界からはっきり分離させる
- Scene: 背景は**完全に均一な #FF00FF のみ**（影・グラデーション・床・照明変化を入れない）
- Avoid: black blobs, stray dark pixels, facial dirt, 机・椅子・モニタ・吹き出し・文字・影
- Identity lock: 確定した髪丈、前髪、髪飾りの側、両目の色、服色を文章で毎行繰り返す。
  「Images 2 and 3のどちらかを自由に選ぶ」とは書かない

### 3. 変えてよいもの / だめなもの（指示書に必ず表で書く）

| 変えてよい | 1ドットも変えてはいけない |
| --- | --- |
| 髪型・髪の長さ・髪色・前髪・髪飾り | 顔（肌の露出部分）の大きさと位置、目鼻口の配置 |
| 瞳の色、眉の形 | 頭頂の高さ、顔の中心x、肩の位置と幅、体の大きさ |
| 服装（色・形・襟・アクセサリ） | 4コマそれぞれのポーズと動きの内容 |
| 肌の色の微調整 | フレーム内の立ち位置、ドットの粒度、輪郭線の太さ |

「髪を増やしたので顔も大きくした」は不合格、と明記する。

### 4. 透過処理 — 暗色キャラを壊さないためのガード

抜き色は **`#FF00FF` 固定。緑背景は禁止**（despillで肌や淡色の服に緑が混ざる事故が起きた）。

暗色（黒髪・ダークネイビーのスーツ）が背景と誤判定されて欠損する事故も起きたので、
必ず次のガードを入れる。実装は
`.claude/skills/pixel-asset-gen/scripts/process_generated_row.py` にある。

- 半透明画素の比率が1.5%を超えたら自動キーの結果を捨て、高彩度マゼンタだけを透明化する
- **暗色・黒に近いRGBは透明化しない**
- 縮小で生じた近黒色の緑/マゼンタ色相は透明化せず `max(r,g,b)` のグレーへ中和する
  （透明化すると黒髪やスーツに穴が開く）。キャラ本来の緑眼などは中和しない
- 最後にアルファを `a >= 128 ? 255 : 0` で2値化する

### 5. 96×96への縮小

固定倍率にしない（モデル出力の寸法は一定でない）。基準シートの各コマの不透明bboxを取り、
生成スプライトを**BOXフィルタでそのbboxサイズに1回だけ縮小**して、同じ座標に整数配置する。
これで位置とサイズが基準に一致する。posterize等の色数削減後処理は禁止（顔が潰れる）。

生成後にシート全体または各フレームへ一律の横・縦補正を追加してはいけない。
特に非等方の `85%x100%` 等を最終検証後に掛けることを禁止する。寸法不良はその行を再生成して直す。

## 検証

```bash
# 基準シートとの突き合わせ（キャラ差し替え方式ではこれが主）
python3 .claude/skills/pixel-asset-gen/scripts/compare_to_reference.py <生成シート> <基準シート>
```

合否に使うのは次の3つ:

- **頭頂y・顔中心x が基準±1px** — ずれると席の中でキャラが動いて見える
- 頭部幅は±10pxまで許容（髪型が変われば正当に変わる）
- **面積比（不透明画素数の比）0.75〜1.35** — 外れたら透過処理でキャラが削れたか背景が残っている

**顔の大きさは数値で測れない。** 色で肌を判定すると明るい髪色やクリーム色の服を肌と
誤検出する。土台を編集する方式なら自動的に揃うので、最終判断は比較画像の目視で行う。

そして最重要: **codexに各行の96px画像を `view_image` で自分の目で確認させる**。
「顔に黒い塊やゴミ画素が無いこと」は数値検査では検出できず、これで8体の不良を潰した。

機械検査の合格はidentityの合格を意味しない。全40フレームについて、確定した髪型・髪丈・
髪飾りの側・瞳色・服色を原寸と400%で確認する。行ごとの一覧だけでなく、各行1コマ目を
順番に切り替える遷移GIFで「状態変更時に別人化・伸縮・ジャンプしないこと」を検査する。

最終候補は最初に `~/work/_tmp/YYYYMMDD_<name>アセット再生成/` へ保存し、比較シート、
全行GIF、遷移GIF、検査ログを添える。人間の目視承認前にruntimeの `pixel_sheet.png` を差し替えない。

## 委譲の実務

- 10体を超える規模なら3〜4体ずつに分けて複数セッション並列（`run_codex.sh -C <作業dir> -p <計画書>`）。
  1体あたり10回の画像生成で15〜25分が目安
- 計画書は自己完結させ、共通仕様は別ファイル（SPEC）にして「最初に必ず読む」と書く
- **成功したセッションに手順を書き出させてから他へ展開する**のが有効だった。
  セッションごとに後処理の実装が違い、品質差が出る
- セッションがハングしても成果物は出来ていることがある。`check_run.sh` の STALLED を
  見たら、まず出力ファイルの検証をしてから再実行を判断する

## 着席構図の制約（アセット設計に直結）

エンジンは着席キャラを机の天板でクリップするため、**フレーム上端から78pxしか画面に出ない**
（実測値。可視範囲 = クリップ線 − (spriteY − 96)）。

- **手を使うモーションは成立しない**。workingは肩の上下・上体の前傾・前髪の揺れで表現する。
  手を机の高さに描くと隠れて静止画に見え、机より上に出すと宙に浮いて不自然になる
- thinking（顎に手）・error（頬に手）・success（万歳）は手が顔の高さなので問題ない
- 背景側で机より上に飛び出す前景物（背の高いモニタ等）は
  `office_bg_slots.json` の `front_rects` で指定する（CONTRACT.md参照）

候補完成後は実際のPixel Workspaceでも確認する。着席時はフレーム上端から約78pxしか見えないため、
workingの動作、thinkingの顎手、successの腕、errorの頬手が机のクリップ後も読めることを確認する。

