Image grid
A/B testing without the squinting or the tab-switching
- image
- dataset
- ui_widget
- image
- dataset
- receipt
- image_list
If you've ever built a "which checkpoint wins?" workflow, you know the pain: eight images on eight separate preview nodes, then you spend the next ten minutes alt-tabbing between tabs trying to remember which one had the better hands. LF_ImageGrid is the fix - it renders a whole set of images into one labeled comparison matrix so the differences are visible in a single glance.
The layout is where it gets interesting. The grid isn't just "images in a row." The image input takes images in row-major order, and if you feed it a dataset, that dataset's columns become the matrix's columns and its nodes become the rows - with column titles rendered above and node values beside each row. No dataset? You get one automatic row and the images are just numbered. That "dataset" comes from LF_WriteJSON (another LF Nodes node), so you can programmatically drive row/column labels from whatever produced the images.
What it does with your pixels
Every cell is rendered to cell_width × cell_height (both default 512) by fitting - images are scaled and letterboxed, never cropped or stretched. gap_px (default 8) spaces cells and headers, background picks black, white, or transparent (transparent gives you an RGBA result), and title puts an optional heading above the whole thing. show_headers turns the column titles and row value labels on or off.
Because it preserves the original aspect ratio inside each cell, the tool is honest about comparisons: mismatched resolutions show up as letterboxing, not as silently deformed previews. That's a feature, though some people find it odd the first time they see uneven boxes.
Inputs and outputs worth knowing
The inputs you'll actually touch: image, cell_width/cell_height (they also let you decide how big each comparison is - drop to 256 if you're comparing 20 at once), background, and show_headers. dataset only matters when you want named rows/columns, and ui_widget is an internal LF Masonry preview you can ignore.
Outputs are image (the rendered matrix - wire it into a SaveImage or preview), dataset (the same LfDataDataset, now with the composed cells), image_list (the matrix as a one-item list, handy for nodes that only eat lists), and receipt, a deterministic lf.image_grid.receipt.v1 layout record.
Installing and gotchas
It ships in the LF Nodes pack - Manager, search "LF Nodes," or:
cd ComfyUI/custom_nodes
git clone https://github.com/lucafoscili/lf-nodes.git
then restart. Manager auto-installs the pack's requirements.txt (heavier stuff like rembg and onnxruntime is for other nodes in the suite; this one just needs torch and Pillow). Note the pack was rewritten and the old repo archived in 2025 - make sure you're on lucafoscili/lf-nodes.
Two things trip people up. First, the grid is bounded by the image input's ordering - if you don't keep your sources in the exact order you want displayed, the labels won't match the pictures, and there's no drag-to-reorder. Second, cell sizes cap at 4096 and there's a total-pixel safety limit, so a 10×10 grid at 1024 cells each isn't happening - drop the cell size. Otherwise this is one of the least finicky image nodes in the pack: feed it a batch, read the result.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Images in row-major order. The LfDataDataset columns define matrix columns and nodes define rows. | |
| cell_width | INT | 51232–4096 | Width of every comparison cell. Images are fitted without cropping or stretching. |
| cell_height | INT | 51232–4096 | Height of every comparison cell. Images are centered and letterboxed when needed. |
| gap_px | INT | 80–1024 | Spacing between matrix cells and headers, in pixels. |
| background | COMBO | black | Letterbox and gap background. Transparent produces RGBA output. |
| show_headers | BOOLEAN | true | Render column titles above the matrix and node values beside each row. |
| title | STRING | Optional title rendered above the complete comparison matrix. | |
| datasetopt | JSON | LfDataDataset from LF_WriteJSON. Columns are the horizontal axis, nodes are rows, and the node fills their cells with the ordered images. Omit for one automatic row. | |
| ui_widgetopt | LF_MASONRY | [object Object] | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | Rendered comparison matrix. |
| dataset | JSON | LfDataDataset whose cells are the images that compose the matrix. |
| receipt | JSON | lf.image_grid.receipt.v1 layout receipt. |
| image_list | IMAGE | Rendered comparison matrix as a one-item image list. |