Image Tile Batch
Tiling That Remembers Where Every Tile Came From
- image
- tiles
- layout
- bbox
- bounding_box
Tiled upscaling is the answer to a specific constraint: an output larger than the model can hold at once. Cut the canvas into overlapping crops, run diffusion on each, blend them back. The reason the technique has a reputation for being fiddly is not the sampling - it is the bookkeeping. Which tile was at which coordinate, how much do neighbouring tiles overlap, which pixels are real and which are the padding someone added to make the tensor rectangular, and where does the seam go when you paste it back. Every one of those answers has to be carried from the tile pass to the stitch, and most node packs just hand you a batch of crops and wish you luck.
This node emits the geometry alongside the tiles.
The three modes, and what actually differs
mode is the parameter to understand; the rest follows from it.
- fixed_tile uses the exact tile size you asked for. The grid count is derived from the overlap arithmetic, and the last row/column of starts is pinned to the far edge so the tiles end flush with the canvas rather than hanging over it.
- bounded_grid caps the grid at
max_columnsandmax_rows, then recomputes the tile size to cover the axis:ceil((source + overlap * (count - 1)) / count). Use it when you would rather have bigger tiles than a 5x5 grid, or when you are limited to a fixed number of sampling passes. - uniform_grid flips the control: you specify minimum counts and minimum overlaps (
min_columns,min_rows,min_overlap_x,min_overlap_y) and it distributes the starts evenly across the full span, hitting both boundaries exactly and keeping the strides balanced to within one pixel. This is the mode for even work distribution - no tiny sliver tile at the right edge.
Defaults are 1024x1024 tiles with 128 pixels of overlap on each axis, capped at a 3x3 grid.
Outputs: the part that makes it worth using
- tiles - an ordinary IMAGE batch in source-major order: image 0's tiles first, then image 1's, index =
source_index * spatial_count + spatial_index. That ordering is the contract the untile node reads back. - layout - the authoritative geometry: version, source batch/size/channels, tile tensor size, rows, columns, the mode and requested parameters, and per-tile records with the source rectangle, the valid rectangle and the neighbour overlaps. Feed it to Image Untile Batch; it is not reconstructable from the tiles alone.
- bbox - a list of
(x, y, width, height)boxes, one per tile, in the same order as the tiles. - bounding_box - the same rectangles as
{x, y, width, height}dicts, for core nodes that want that structure.
Two things about the geometry are easy to miss and both are handled for you. Tiles at the right and bottom edges are padded to full tile size by repeating the last real pixel, so the batch is uniform - but the layout also records the valid rectangle, so the untile only blends real content. And because the edge tiles are shifted back to the boundary rather than centred, the actual overlap on the final column is whatever is left over, not exactly your requested value. The layout knows the truth; you do not have to.
Install
Part of ComfyUI-Utility-Suite. ComfyUI Manager → search ComfyUI-Utility-Suite → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/tom-m-2020/ComfyUI-Utility-Suite
Restart ComfyUI. It is pure geometry - no models, no downloads, nothing to configure beyond the pack's opencv-python-headless dependency. The tiling nodes are written with the newer V3 node API, so a current ComfyUI is required. Remember this node only cuts; the sampling happens wherever you send the tiles batch, and it is the ControlNet Tile condition (or an equivalent reference) per tile that keeps the crops from inventing different content.
Traps
Overlap has hard limits. overlap_x must be smaller than tile_width and no more than half of it; same on the other axis. Violating it is an error, not a clamp.
A tile bigger than the source is a single tile. That is correct and occasionally surprising when a 900px test image quietly produces one tile.
uniform_grid refuses to fudge. If you ask for min_columns: 2 on a source no wider than the tile, or request more distinct starts than pixels allow, it raises instead of silently downgrading. Read the message - it tells you which axis and which constraint.
bbox here is width/height, not x2/y2. The boxes coming out of SEGS in the same pack are xyxy. If you mix the two families, run them through BBOX xywh to xyxy rather than hoping.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mode | COMBO | 3 options: fixed_tile, bounded_grid, uniform_grid | |
| tile_width | INT | 10241–32768 | — |
| tile_height | INT | 10241–32768 | — |
| overlap_x | INT | 1280–16384 | — |
| overlap_y | INT | 1280–16384 | — |
| max_columns | INT | 31–256 | — |
| max_rows | INT | 31–256 | — |
| min_overlap_x | INT | 1280–32768 | — |
| min_overlap_y | INT | 1280–32768 | — |
| min_columns | INT | 11–32768 | — |
| min_rows | INT | 11–32768 | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| tiles | IMAGE | — |
| layout | TILE_LAYOUT | — |
| bbox | BBOX | — |
| bounding_box | BOUNDING_BOX | — |