タイルを格子で分割

タイルの大きさを指定し、格子画像を個別PNGに分割。

タイルセットを1枚ずつの画像に切るには、軸ごとに3つの数値が必要です。タイルサイズ、余白(最初のタイルの前のピクセル)、間隔(タイルの間のピクセル)です。このツールはピクセルからそれらを測って候補に順位を付け、確認か入力をすると、範囲をそのままコピーしたtiles/tile-NNN.pngと、各タイルの範囲・列・行を記したmetadata.jsonを書き出します。空のタイルは既定で飛ばし、重複はエイリアスとして示せます。ほとんどのエンジンは同じ余白・間隔でシート全体を読むので、個別のファイルが必要なのはツールが求めるときだけです。

画像をここにドロップ複数のファイルをまとめて処理できます
アップロードなし · この端末で処理

タイルサイズ・余白・間隔

列c・行rのタイルはx = 余白 + c × (タイル幅 + 間隔)、y = 余白 + r × (タイル高さ + 間隔)から始まります。収まる列数はfloor((画像の幅 − 余白 + 間隔) ÷ (タイル幅 + 間隔))で、右端や下端に余ったピクセルは無視します。各タイルはデコードしたシートから正確な矩形としてコピーし、リサンプリングしません。

測定は絵の周期を探します。軸ごとに各行と前の行の差でプロファイルを作り、4pxから画像の半分までのすべての周期で折り返して、それぞれがプロファイルをどれだけ説明するかを採点します。余白や間隔が占める行は空か単色でなければならず、どのタイルも最初か最後の行が空ならタイルはもっと小さくその行が間隔です(「16px + 1pxの間隔」が「17pxのタイル」に勝つ)。本当の周期の倍数は約数に負けます。4メガピクセルを超えると測定せず、サイズを入力します。

エンジンはシート全体に同じ数値を使います。Godot 4のTileSetAtlasSourceにはmargins、separation、texture_region_size、Tiledの画像ベースのタイルセットにはmarginとspacing、PhaserのaddTilesetImageにはtileMarginとtileSpacing、UnityのSprite Editorのグリッド分割にはPixel Size・Offset・Paddingがあります。タイルごとに自分の画像ファイルを指すTiledの「Collection of Images」タイルセットだけが個別のPNGを必要とします。

余白(margin)
画像の端と最初のタイルの間のピクセル。
間隔(spacing、separation)
隣り合う2つのタイルの間のピクセル。
空のタイル
すべてのピクセルのアルファが0のタイル。既定で飛ばし、skippedBlankで数えます。
エイリアス
前のタイルとまったく同じタイル。1回だけ書き、対応をaliasesに記録します。

例:16pxのタイル、間隔1pxの203 × 186のシート

ツールが使う数値と、同じ配置を3つのエンジンに入れる値です。

シート    203 × 186、タイル 16 × 16、余白0、間隔1
列        floor((203 − 0 + 1) / (16 + 1)) = floor(204 / 17) = 12
行        floor((186 − 0 + 1) / 17) = floor(187 / 17) = 11   → タイル132枚
13番      1列、1行 → x = 0 + 1 × 17 = 17, y = 17、16 × 16 → tiles/tile-013.png
名前      1000枚までは3桁(tile-005)、それ以上は4桁(1600枚のシートでtile-0005)
別の例    100 × 64のシート、余白1、間隔2 → 5 × 3タイル、x = 1, 19, 37, 55, 73;右の11pxは未使用
エンジン  Godot margins (0, 0), separation (1, 1) · Tiled margin 0, spacing 1 · Phaser addTilesetImage(name, key, 16, 16, 0, 1)

ファイル名はタイルのグリッド番号を保つので、空のタイルを飛ばすと番号に意図的な欠番ができます。tile-013はこのシートで常に1列1行です。

結果の確認

  • グリッド線を表示します。すべての線がすき間かタイルの境目にあり、絵を横切らないはずです。
  • metadata.jsonを開きます。tileSet.columns × rowsがグリッド、countが書き出したファイル数で、差はskippedBlankとdeduplicatedで説明されます。
  • タイルのPNGを1つ開きます。ちょうどタイルサイズで、framesのrectがx = 余白 + 列 × (タイル + 間隔)を満たすはずです。

トラブルシューティング

症状考えられる原因確認方法対処
すべてのタイルに隣のタイルの線が付く・1ピクセルずれる余白か間隔が違う。多いのは16 + 1ではなく17pxのタイルグリッド線がすき間ではなく絵を横切っている順位リストの別の候補を選ぶか、余白・間隔を入力する
グリッドのタイル数よりファイルが少ない空のタイルを飛ばした、または重複をエイリアスとして1回だけ書いたmetadata.jsonのskippedBlank、deduplicated、aliasesグリッドのセルごとにファイルが要るなら、空タイルのスキップや重複検出を切る
タイルは16pxなのに32pxの周期が見つかる絵がより大きな模様を繰り返し、タイルの倍数も高得点になる16pxと32pxの候補の得点を比べる16pxの候補を選ぶかサイズを入力する
タイルサイズがまったく提案されない画像が4メガピクセルを超え、グリッドを測定しない欄が空で、入力するよう案内が出るタイルサイズ・余白・間隔を入力する。分割はそのまま動く

ほかの方法

方法こんなときに向いています
エンジンで余白・間隔を指定してシート全体を読み込むほぼすべてのタイルマップ。GodotのTileSetAtlasSource、Tiledの画像ベースのタイルセット、PhaserのaddTilesetImageは画像1枚を読むので、管理するタイルファイルがありません。
タイルセット分割個別のPNGではなく、Godot・Tiled・Unity・LDtk向けの地形ルールつきのエンジン用タイルセットが必要なとき。
UnityのSprite Editor、Grid By Cell SizeシートをUnityだけで使うとき。Pixel Size・Offset・PaddingでUnityのインポート内にスプライトの範囲を作ります。

この方法の限界

  • 1回の分割は最大4096タイル、類似タイルのまとめは2048タイルまでです。
  • ZIPにエンジン用のタイルセットは入りません。metadata.jsonは範囲・列・行を持つ汎用の形式です。

バージョンと出典

docs/TILE-LAB.mdのために測定しました。合成シート10枚中10枚で本当のグリッドが1位(余白1・間隔2、奇数の15px、16 × 32のタイル、アウトラインつきのタイル)、切り出したタイル13枚中13枚が元の範囲とバイト一致(Chromium + Pillow)、48枚中47枚を書き出して空タイル1枚を飛ばしエイリアス1つ、8pxのタイル1600枚を2.2秒で分割しキャンセルも動作しました。エンジンのパラメーター名はGodot 4.7、Tiled、Phaser、Unityの公式ドキュメントに基づきます。

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

使用例

元の図形サンプル · 96 × 64
元の図形サンプル · 96 × 64
処理後のサンプル · 32 × 32
処理後のサンプル · 32 × 32

このツールで作成した例です。ZIPツールはプレビューを表示します。すべてのファイルはダウンロードしたZIPで確認してください。

タイルを格子で分割

タイルの大きさを指定し、格子画像を個別PNGに分割。

使い方

  1. 画像を追加
  2. 設定を調整して結果を確認
  3. 新しいファイルを保存

対応形式

PNG / JPG / WebP / AVIF / HEIC → PNG + JSON (ZIP) — 入力のデコードはブラウザ対応と追加エンジンに依存します。

このツールでできること

タイルの大きさを指定し、格子画像を個別PNGに分割。

処理方式と検証状況

advanced · exact grid region copy. 品質検証中です。Pro・Flagship水準はまだ実証されていません。

書き出す前に

画像を割り切れるタイルサイズが必要です。オートタイル規則は生成しません。

よくある質問

このツールにはどのような制限がありますか?

画像を割り切れるタイルサイズが必要です。オートタイル規則は生成しません。

ファイルはアップロードされますか?

このツールで開いたファイルはアップロードせず端末で処理します。コミュニティの投稿に明示的に添付する画像は別途アップロードされます。一部のエンジンやモデルは外部から取得するため、IPアドレスなどの接続情報は配信元に伝わります。

作業は自動保存されますか?

いいえ。画像と編集状態はこのタブに保持され、メディア出力は端末の一時保存を利用する場合があります。言語を変えても作業は残りますが、再読み込み、タブを閉じる操作、別のページへの移動で失われることがあります。