Nodes/ComfyUI-TinyBee/Grid Maker (Dynamic)
ComfyUI Node

Grid Maker (Dynamic)

A contact sheet without the export detour

By TinyBeeman·Created about a year ago·Updated about a month ago· 1
Grid Maker (Dynamic)
  • img_0_0
  • img_0_1
  • img_0_2
  • img_0_3
  • img_0_4
  • img_0_5
  • img_0_6
  • img_0_7
  • img_0_8
  • img_0_9
  • img_1_0
  • img_1_1
  • img_1_2
  • img_1_3
  • img_1_4
  • img_1_5
  • img_1_6
  • img_1_7
  • img_1_8
  • img_1_9
  • img_2_0
  • img_2_1
  • img_2_2
  • img_2_3
  • img_2_4
  • img_2_5
  • img_2_6
  • img_2_7
  • img_2_8
  • img_2_9
  • img_3_0
  • img_3_1
  • img_3_2
  • img_3_3
  • img_3_4
  • img_3_5
  • img_3_6
  • img_3_7
  • img_3_8
  • img_3_9
  • img_4_0
  • img_4_1
  • img_4_2
  • img_4_3
  • img_4_4
  • img_4_5
  • img_4_6
  • img_4_7
  • img_4_8
  • img_4_9
  • img_5_0
  • img_5_1
  • img_5_2
  • img_5_3
  • img_5_4
  • img_5_5
  • img_5_6
  • img_5_7
  • img_5_8
  • img_5_9
  • img_6_0
  • img_6_1
  • img_6_2
  • img_6_3
  • img_6_4
  • img_6_5
  • img_6_6
  • img_6_7
  • img_6_8
  • img_6_9
  • img_7_0
  • img_7_1
  • img_7_2
  • img_7_3
  • img_7_4
  • img_7_5
  • img_7_6
  • img_7_7
  • img_7_8
  • img_7_9
  • img_8_0
  • img_8_1
  • img_8_2
  • img_8_3
  • img_8_4
  • img_8_5
  • img_8_6
  • img_8_7
  • img_8_8
  • img_8_9
  • img_9_0
  • img_9_1
  • img_9_2
  • img_9_3
  • img_9_4
  • img_9_5
  • img_9_6
  • img_9_7
  • img_9_8
  • img_9_9
  • grid_image
  • cell_width
  • cell_height
rows2
cols2

You've generated a batch of variants and now you want to see them all at once - side by side, same size, in a grid you can actually compare. The lazy way is saving everything and stitching in an external editor. Grid Maker (Dynamic) is the in-graph way: it takes up to 100 individual image inputs, arranges them into a clean rows×cols grid, and hands you a single composite image plus the cell dimensions.

The "Dynamic" in the name is the point. Instead of a fixed 2×2 or 3×3 layout, you tell it how many rows and columns you want (up to 10×10) and it fills the grid from a bank of optional image inputs named img_0_0, img_0_1, and so on. Set rows=3, cols=3 and it reads img_0_0 through img_2_2. Bump it to 4×4 and more of those inputs come into play. Same node, no rebuilding.

How it works

The node sizes each cell from the first image it receives - img_0_0 if it's connected, otherwise the first filled slot. Every other image is then fitted into that cell canvas: larger images get cropped to the cell, smaller ones sit in the top-left corner of a zero-filled canvas. Then it tiles them: images concatenate horizontally per row, rows stack vertically, and out comes one grid_image tensor plus cell_width and cell_height so downstream nodes know what they're dealing with.

The inputs that matter:

  • rows and cols (INT, 1–10, default 2) - the grid layout. These decide which img_r_c slots are read.
  • img_0_0 through img_9_9 (optional IMAGE) - the 100 candidate slots. Connect only the ones your current grid uses; the rest stay empty.

The outputs are grid_image (the composite), plus cell_width and cell_height (the size each tile was fitted to).

Installing it

Grid Maker (Dynamic) is part of ComfyUI-TinyBee, a small MIT-licensed utility pack with no model downloads. Via Manager:

  1. ComfyUI Manager → Custom Nodes Manager.
  2. Search "ComfyUI-TinyBee" and install.
  3. Restart ComfyUI.

Or clone:

cd ComfyUI/custom_nodes
git clone https://github.com/TinyBeeman/ComfyUI-TinyBee

Restart and it's under 🐝TinyBee/Images. No special dependencies - the pack's jsonata requirement only affects its JSON Parser node.

Gotchas

The big one: images are not resized to fit the cell. Fit means "copy the top-left region that fits and pad the rest" - so a 1024×1024 image next to a 512×512 one will be cropped to the smaller cell, not scaled down. If you're gridding images of different sizes, normalize them (resize) before they hit this node, or you'll get surprising crops. Also, all images in a grid must share the same channel count and dtype, which they will if they come from one pipeline. The output grid is a single image, so wire it into a preview or a Save Image node - and if you want to shuffle which images land in which cell, run your batch through Randomize Image Batch first and split it out.

Category🐝TinyBee/Images

Inputs (102)

NameTypeDefaultDescription
rowsINT21–10
colsINT21–10
img_0_0optIMAGE
img_0_1optIMAGE
img_0_2optIMAGE
img_0_3optIMAGE
img_0_4optIMAGE
img_0_5optIMAGE
img_0_6optIMAGE
img_0_7optIMAGE
img_0_8optIMAGE
img_0_9optIMAGE
img_1_0optIMAGE
img_1_1optIMAGE
img_1_2optIMAGE
img_1_3optIMAGE
img_1_4optIMAGE
img_1_5optIMAGE
img_1_6optIMAGE
img_1_7optIMAGE
img_1_8optIMAGE
img_1_9optIMAGE
img_2_0optIMAGE
img_2_1optIMAGE
img_2_2optIMAGE
img_2_3optIMAGE
img_2_4optIMAGE
img_2_5optIMAGE
img_2_6optIMAGE
img_2_7optIMAGE
img_2_8optIMAGE
img_2_9optIMAGE
img_3_0optIMAGE
img_3_1optIMAGE
img_3_2optIMAGE
img_3_3optIMAGE
img_3_4optIMAGE
img_3_5optIMAGE
img_3_6optIMAGE
img_3_7optIMAGE
img_3_8optIMAGE
img_3_9optIMAGE
img_4_0optIMAGE
img_4_1optIMAGE
img_4_2optIMAGE
img_4_3optIMAGE
img_4_4optIMAGE
img_4_5optIMAGE
img_4_6optIMAGE
img_4_7optIMAGE
img_4_8optIMAGE
img_4_9optIMAGE
img_5_0optIMAGE
img_5_1optIMAGE
img_5_2optIMAGE
img_5_3optIMAGE
img_5_4optIMAGE
img_5_5optIMAGE
img_5_6optIMAGE
img_5_7optIMAGE
img_5_8optIMAGE
img_5_9optIMAGE
img_6_0optIMAGE
img_6_1optIMAGE
img_6_2optIMAGE
img_6_3optIMAGE
img_6_4optIMAGE
img_6_5optIMAGE
img_6_6optIMAGE
img_6_7optIMAGE
img_6_8optIMAGE
img_6_9optIMAGE
img_7_0optIMAGE
img_7_1optIMAGE
img_7_2optIMAGE
img_7_3optIMAGE
img_7_4optIMAGE
img_7_5optIMAGE
img_7_6optIMAGE
img_7_7optIMAGE
img_7_8optIMAGE
img_7_9optIMAGE
img_8_0optIMAGE
img_8_1optIMAGE
img_8_2optIMAGE
img_8_3optIMAGE
img_8_4optIMAGE
img_8_5optIMAGE
img_8_6optIMAGE
img_8_7optIMAGE
img_8_8optIMAGE
img_8_9optIMAGE
img_9_0optIMAGE
img_9_1optIMAGE
img_9_2optIMAGE
img_9_3optIMAGE
img_9_4optIMAGE
img_9_5optIMAGE
img_9_6optIMAGE
img_9_7optIMAGE
img_9_8optIMAGE
img_9_9optIMAGE

Outputs (3)

NameTypeDescription
grid_imageIMAGE
cell_widthINT
cell_heightINT