Tile Grid Slicer

Split a tile grid into individual PNGs at an exact tile size.

Cutting a tileset into single images takes three numbers per axis: the tile size, the margin (pixels before the first tile) and the spacing (pixels between tiles). The slicer measures them from the pixels and ranks the candidates, you confirm or type them, and it writes tiles/tile-NNN.png as exact region copies plus metadata.json with each tile's rect, column and row. Blank tiles are skipped by default and duplicates can be reported as aliases. Most engines read the whole sheet with the same margin and spacing, so single files are only needed when a tool asks for them.

Drop image files hereProcess many files at once
No upload · processed on this device

Tile size, margin and spacing

Tile n in column c and row r starts at x = margin + c × (tile width + spacing) and y = margin + r × (tile height + spacing). The number of columns that fit is floor((image width − margin + spacing) ÷ (tile width + spacing)); pixels left over at the right or bottom edge are ignored. Each tile is copied out of the decoded sheet as an exact rectangle, never resampled.

Measurement looks for the period of the art: per axis it builds the difference between each line and the one before, folds that profile at every period from 4 px to half the image and scores how well each fold explains it. Lines that a margin or spacing would reserve must be blank or flat, a blank first or last line inside every tile means the tile is smaller and that line is spacing ("16 px + 1 px gap" beats "17 px tiles"), and a multiple of the true period loses to its divisor. Above 4 megapixels nothing is measured and the size is typed in.

Engines take the same numbers for the whole sheet: Godot 4's TileSetAtlasSource has margins, separation and texture_region_size, Tiled's image-based tileset has margin and spacing, Phaser's addTilesetImage takes tileMargin and tileSpacing, and Unity's Sprite Editor grid slicing has Pixel Size, Offset and Padding. Only a Tiled "Collection of Images" tileset, where each tile refers to its own image file, needs the single PNGs.

Margin
Pixels between the image edge and the first tile.
Spacing (separation)
Pixels between two neighbouring tiles.
Blank tile
A tile whose every pixel has alpha 0; skipped by default and counted in skippedBlank.
Alias
A tile identical to an earlier one; written once and mapped in aliases.

Example: a 203 × 186 sheet with 16 px tiles and 1 px spacing

The numbers the slicer uses, and the same layout in three engines:

sheet     203 × 186, tiles 16 × 16, margin 0, spacing 1
columns   floor((203 − 0 + 1) / (16 + 1)) = floor(204 / 17) = 12
rows      floor((186 − 0 + 1) / 17) = floor(187 / 17) = 11   → 132 tiles
tile 13   column 1, row 1 → x = 0 + 1 × 17 = 17, y = 17, 16 × 16 → tiles/tile-013.png
names     3 digits up to 1000 tiles (tile-005); 4 digits above (tile-0005 in a 1600-tile sheet)
other     100 × 64 sheet, margin 1, spacing 2 → 5 × 3 tiles at x = 1, 19, 37, 55, 73; 11 px on the right are unused
engines   Godot margins (0, 0), separation (1, 1) · Tiled margin 0, spacing 1 · Phaser addTilesetImage(name, key, 16, 16, 0, 1)

File names keep the tile's grid index, so when blank tiles are skipped the numbering has gaps on purpose: tile-013 is always column 1, row 1 of this sheet.

Check the result

  • Turn on the grid lines: every line should fall in a gap or on a tile edge, never through the art.
  • Open metadata.json: tileSet.columns × rows is the grid, count the files written, skippedBlank and deduplicated explain any difference.
  • Open one tile PNG: it is exactly the tile size, and its rect in frames satisfies x = margin + col × (tile + spacing).

Troubleshooting

SymptomLikely causeHow to checkFix
Every tile carries a line of its neighbour or is shifted by a pixelWrong margin or spacing, typically 17 px tiles instead of 16 + 1Grid lines cross the art instead of the gapsPick the other candidate in the ranked list, or type the margin and spacing
Fewer files than tiles in the gridBlank tiles are skipped, or duplicates were written once as aliasesskippedBlank, deduplicated and aliases in metadata.jsonTurn blank skipping or duplicate detection off to get one file per grid cell
The period found is 32 px but the tiles are 16 pxThe art repeats a larger pattern, so a multiple of the tile scores wellCompare the scores of the 16 px and 32 px candidatesChoose the 16 px candidate or type the size
The tile size is not suggested at allThe image is above 4 megapixels, where the grid is not measuredThe field is empty and the note says to type itType the tile size, margin and spacing; slicing still works

Other ways to do it

OptionWhen it is the better choice
Load the whole sheet in the engine with the margin and spacingAlmost every tilemap: Godot TileSetAtlasSource, a Tiled image-based tileset or Phaser addTilesetImage read one image and no tile files have to be managed.
Tileset slicerYou need an engine tileset with terrain rules for Godot, Tiled, Unity or LDtk rather than loose PNGs.
Unity Sprite Editor, Grid By Cell SizeThe sheet is only used in Unity: Pixel Size, Offset and Padding create the sprite rects inside Unity's importer.

What this page does not cover

  • At most 4096 tiles per slice; near-duplicate grouping is capped at 2048 tiles.
  • The ZIP carries no engine tileset; metadata.json is the generic envelope with rects, columns and rows.

Versions and sources

Measured for docs/TILE-LAB.md: the true grid ranked first on 10 of 10 synthetic sheets (margin 1 with spacing 2, odd 15 px, 16 × 32 tiles, outlined tiles); 13 of 13 sliced tiles byte-identical to their source regions (Chromium + Pillow); 47 of 48 tiles written with 1 blank skipped and 1 alias; 1600 tiles of 8 px sliced in 2.2 s with a working cancel. The engine parameter names follow the Godot 4.7, Tiled, Phaser and Unity documentation.

Official documentation used

Example

Original geometric sample · 96 × 64
Original geometric sample · 96 × 64
Processed sample · 32 × 32
Processed sample · 32 × 32

Example generated with this tool. ZIP tools show their preview; inspect the downloaded archive for every file.

Tile Grid Slicer

Split a tile grid into individual PNGs at an exact tile size.

How it works

  1. Add images
  2. Adjust settings and review the result
  3. Download a new file

Supported formats

PNG / JPG / WebP / AVIF / HEIC → PNG + JSON (ZIP) — Input decoding depends on browser support and optional engines.

What this tool does

Split a tile grid into individual PNGs at an exact tile size.

Implementation and verified quality

advanced · exact grid region copy. Quality qualification is in progress. Pro/Flagship quality has not been established.

Before you export

Tile size must divide the image exactly. Autotile rules are not generated.

Frequently asked questions

What are this tool’s limitations?

Tile size must divide the image exactly. Autotile rules are not generated.

Are my files uploaded?

This tool processes the files you open on your device without uploading them. Images you explicitly attach to community posts are uploaded separately. Optional engines and models are downloaded from third parties; those requests expose connection information such as your IP address.

Will my work be saved automatically?

No. Images and editing state stay in this tab; media output can use local temporary storage. Changing language preserves your work; reloading, closing the tab, or following a link to another page can clear it.