本文へスキップ

ドット絵パレット固定 · 全フレームでひとつのパレット

別々のツールから書き出したフレームはパレットがばらばらです。ピクセルラボは全フレームからひとつのパレットを作って各フレームを固定し、書き出した全色がパレット内にあることを確認します。

別々のツールから書き出したり、サイズを変えて保存し直したりしたフレームは、色が少しずつずれます。同じ陰影が微妙に違う3色になり、アニメがちらつきます。ロックはこれを直します。全フレームを合わせて1つのパレットを作り(2〜256色、既定16色、またはPICO-8などのプリセット)、全フレームの全ピクセルをそこへ対応づけ、ディザはオフか組織的ディザにして止まっている部分がちらつかないようにします。ピクセルラボはこれをブラウザで行い、フレームを1×〜8×のPNG、パレットを.gpl、概要をpixel-lab.jsonで書き出し、書き出した全色がパレット内にあることを確認します。

スプライトのフレーム(PNG)をドロップ。複数フレームでひとつのパレットを共有します
ピクセルラボを開く
ブラウザ内で処理し、ファイルはアップロードされません。
ピクセルラボ:抽出した1つのパレットに固定したCC0スプライトのフレームと色ごとのピクセルの割合
CC0アセット(OpenGameArt)を開いた実際のピクセルラボ画面です。
出力
  • PNG frames測定確認· Pillow
  • Palette測定確認· re-import
  • pixel-lab.json未検証

フレームの色がずれる理由と、1つのパレットと適切なディザで防ぐ方法

フレームを通るツールはどれも色を少し動かし得ます。リサンプリングは隣のピクセルを混ぜ、JPEGや非可逆WebPはノイズを加え、色をアルファで乗算して保持するキャンバスは半透明のピクセルをずらします。そうしたフレームを1枚ずつ減色すると、フレームごとに違うパレットになります。ラボは代わりに全フレームをアルファで重み付けした1つのヒストグラムに入れ、Oklabでメディアンカットして(頻度と見た目の差の両方を反映)整え、全フレームが共有する1つのパレットを作ります。

ちらつくかどうかはディザ次第です。組織的(Bayer)ディザはピクセルの位置だけで決まる偏りを加えるので、変わらない部分はどのフレームでも同じピクセルになります。誤差拡散(Floyd–Steinberg、Atkinson)は丸めの誤差をフレーム全体へ運ぶため、1ピクセル動くだけでその後の全ピクセルの判定が変わり、止まっている壁までちらつくことがあります。ラボの既定は「なし」で、複数フレームで誤差拡散を選ぶと警告します。

ラボはキャンバスを通さず、RGBAの値から直接PNGを書きます。キャンバスは半透明の色を乗算済みアルファで丸めてしまうからです。この変更の前は、16色にロックしたパレットの外に書き出した84色のうち68色がはみ出していましたが、変更後は1色もはみ出しません。

パレットロック
全フレームの全ピクセルを、決まった1つのパレットに対応づけること。
メディアンカット
目標の色数になるまで、色のヒストグラムを最も広い軸の中央値で分け続ける方法。
組織的(Bayer)ディザ
ピクセルの位置で決まる固定のしきい値パターン。フレーム間でちらつかない。
誤差拡散
各ピクセルの丸め誤差を隣へ広げるディザ。アニメではちらつくことがある。

例:アンチエイリアスのかかった8フレームを16色にロック

ラボのブラウザテストで、書き出したファイルは別のデコーダーで読み直しています。

入力        8フレーム × 48×48 px = 18,432 px、アンチエイリアスの縁
抽出        8フレーム全体から16色のパレットを1つ
ロック      全ピクセル → Oklabで16色中最も近い色、ディザなし
確認        書き出した全PNGの色:16色、パレット外:0色
ちらつき    変化しない帯:8フレームで1通りだけ(なし、Bayer 4×4とも)
色数の計数  全フレーム面積4MPまで正確、ここでは0.018MP
サイズ上限  1フレームあたり最大4096 × 4096 px

ゲームにとって大事なのは最後の確認です。プレビューではなく書き出したPNGを開いて色を数えてください。ラボのテストもPillowでまさにそうしています。

できること

  • 全フレームからアルファ加重のパレットを1つ作成(Oklabのメディアンカット、2〜256色)。ゲームボーイ・PICO-8・Sweetie 16・Endesga 32・NESのパレットも使えます。
  • ディザー:なし、Floyd–Steinberg、Atkinson、Bayer 2×2/4×4/8×8。組織的ディザーはフレーム間でちらつかず、誤差拡散を選ぶと警告します。
  • パレット編集:明度・色相・彩度・頻度で並べ替え、再抽出しても残る色をロック。
  • PNGフレーム(1×〜8×ニアレスト)、.gplパレット、JSONで書き出し。

使い方

  1. フレームをドロップ。
  2. 色数か定番パレットを選ぶ。
  3. ディザー方式を選ぶ(アニメーションは既定の「なし」)。
  4. ZIPで書き出し。

ロックしたフレームを確認する

  • ← →でフレームを移ります。同じ陰影はどのフレームでもパレットの同じ見本として表示されるはずです。
  • 書き出したPNGを2枚、任意の画像エディタで開き、止まっている部分の同じ位置の色を調べます。値は完全に一致するはずです。
  • 書き出した1フレームの色数を別のツールで数えます。パレットの色数を超えてはいけません。
  • 書き出した.gplをGIMPかAsepriteで読み込みます。同じ色が同じ順で並ぶはずです。

トラブルシューティング

症状考えられる原因確認方法対処
ロック後にアニメがちらつく誤差拡散のディザ(Floyd–SteinbergかAtkinson)がオン変換の工程にちらつきの警告が出る「なし」かBayerに切り替え、ディザ比較のグリッドで並べて見る
小さなディテールの色が消えたメディアンカットは使われるピクセル数で色を重み付けするので、2ピクセルの目のハイライトは広い面に負ける抽出後、パレットの工程にその色があるか確認その色をロックして「もう一度抽出」するか、色数を増やす
ドロップしたスプライトシートが1フレームになったラボは1枚の画像を1フレームとして扱い、シートは分割しないフレームの列が1つだけ先にスプライトスライサーで分割してからフレームをドロップ
ラボが画像を受け付けない4096 × 4096pxを超えるフレームはタブを固めるので拒否するメッセージにサイズと上限が表示される先に縮小・トリミングするか、フレームに分割する
色数が1フレーム分しか数えられていない全フレーム面積が4MPを超えると、表示中のフレームだけを数える数値の横のパネルにその旨が出る正確な合計が必要なら一度に読み込むフレームを減らす

ほかの方法

方法こんなときに向いています
Studioのピクセル作業画面で変換フレームがタイムライン付きのレイヤースプライトなら、カラーモード…がレイヤーとタグを保ったままインデックスにします。パレットエディタを参照。
抽出ではなく公開パレットを使うPICO-8やEndesga 32など決まったパレットに合わせるならLospecパレットの適用。
アンチエイリアスの縁と孤立ピクセルの整理ロック後も変な縁のピクセルや点が残るなら、ラボの整理の工程。ドット絵の整理を参照。

出力ファイルと検証方法

「測定確認」は、ダウンロードしたファイルをページ外(Pillow・numpy・独立したパーサー)で開き直して性質を測ったという意味です。ゲームエンジンでの読み込みは試していません。

書き出し先ファイル検証
PNG framesanim_N.png · 1×–8× nearest測定確認 Pillow書き出したPNGを読み直し、すべての色が固定パレット内にあることを確認。
Palette.gpl · .hex (Lospec) · .json測定確認 re-import各形式を書き出してUIで読み戻し、16 → 16色を確認。
pixel-lab.jsongeneric frames + palette未検証汎用JSONで、どのエンジンでも読み込んでいません。

検証の根拠

アンチエイリアスのかかった8フレーム → 16色パレット1つ、パレット外の色0。ディザーなしとBayer 4×4の両方で変化のない領域が全8フレームで同一。アンチエイリアス除去で271色 → 16色、シルエットの移動0ピクセル。整数倍率・オフセット・2.5倍の非整数倍率を正確に検出。

制限

  • アニメーションの再生はなく、フレームは1枚ずつ送って確認します。
  • 処理はすべてメインスレッドで動き、キャンセルボタンがないため、とても大きな一括処理は終わるまでタブが止まります。
  • 確認はChromiumのみです。
  • 4096 × 4096より大きいフレームは受け付けません。すべての処理がメインスレッドで動き、まだキャンセルボタンがありません。
  • スプライトシートは1枚の画像として扱います。先にフレームに分割してください(スプライトシート分割)。
  • ディザーを有効にすると、クリーンアップの件数にディザーのピクセルが含まれます。先にディザーを「なし」にしてください。
  • 書き出すJSONは汎用形式で、Godot・Unityへの読み込みは試していません。

バージョンと出典

Nerulio:docs/PIXEL-LAB.md。ビルドしたサイトでPlaywrightによりChromiumを動かして測定し、すべての数値はダウンロードしたファイルを読み直して(Pillow、zipfile、json)確認しました。単体テストはtests/game-palette.test.mjsです。書き出す.gplはGIMPのパレット形式に従います。

参照した公式ドキュメント

よくある質問

ディザー後にアニメーションがちらつくのはなぜ?

誤差拡散は誤差を画像全体に運ぶため、1ピクセル動くだけで後の判定が変わります。組織的(Bayer)ディザーは位置だけで決まるのでちらつきません。ラボの既定は「なし」です。

Lospecのパレットを使えますか?

はい。LospecのHEXリスト、.gpl、JSONを貼り付けるか読み込むと、フレームがそのパレットに固定されます。

無料ですか?アカウントは必要ですか?

このページの機能はすべて無料で、アカウントなしで使えます。透かしや制限された書き出しはありません。

スプライトはアップロードされますか?

いいえ。Studioはこのブラウザのタブ内でデコード・パック・書き出しを行います。プロジェクトはブラウザ(IndexedDB)に自動保存され、.nerulioファイルとして保存できます。

Asepriteやエンジンのプラグインは必要ですか?

いいえ。.asepriteファイルはブラウザで読み書きします。エンジン別のバンドルには必要なものが入っています(Godotはインポート設定とシーン、UnityとGodotのタイルセットは小さなエディタースクリプト)。