Sheet Compositor
Tidy contact sheet from messy renders — auto-crop and line them up
- sheets
- contact_sheet
If you've ever generated a character-sheet sequence, you know the raw output is usually a mess: each view floating in a grey void, different amounts of dead space around the figure, nothing aligned. Sheet Compositor fixes that in one step. It takes an IMAGE batch of your generated sheets, finds the actual figure in each, crops out the empty space, scales everything to a common height, and lays the views side by side into one clean contact sheet.
Why bother? Because that single contact sheet is the pack's identity-lock input. One tidy image containing every view of your character, connected to Story Frame Generator's reference_images, keeps that character consistent across an entire story - every frame gets conditioned on the whole reference sheet. You could hand-assemble this in an image editor, but then it's not in the graph, and it doesn't re-run when you re-render the views.
How it works
The mechanism is refreshingly un-mysterious. The sheet renders from Asset Sheet Director are produced on a fixed grey background (#d9d9d9), so the node:
- Finds every pixel that differs from that grey by more than
bg_threshold- those are "foreground." - Computes the bounding box of the foreground and crops to it, keeping a small
padding_pctmargin. - Scales each crop to a common
row_height, preserving aspect ratio. - Pastes them onto a grey canvas, side by side, with
spacingbetween and around them.
Output is a single contact_sheet IMAGE. That's the whole node - four settings, one output.
The settings
row_height(default 512) - the common height all figures are scaled to.spacing(default 24) - the gap between figures and the edges.padding_pct(default 0.04) - a small margin kept around each detected figure.bg_threshold(default 16) - how far a pixel must differ from#d9d9d9to count as foreground.
The only one you'll realistically fiddle with is bg_threshold. If your figure blends into the background (say, a white-shirted character on a light grey), raise it or the crop will swallow part of the subject; if you're getting stray specks detected as foreground, lower it.
Wiring and install
Typical chain:
Asset Sheet Director → Ollama → Story Frame Generator → Sheet Compositor → contact_sheet
The sheets input takes any IMAGE batch - the frames output of Story Frame Generator connects straight in. The result goes to a Preview/Save Image, and for a full identity-locked story you'd also feed the contact sheet into Story Director (with has_references on) and into Story Frame Generator's reference_images.
Part of ComfyUI-ZFRNodes. Via ComfyUI Manager (search "ComfyUI-ZFRNodes") or:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/zfrsgtcu/ComfyUI-ZFRNodes.git
Full restart of ComfyUI after install, as with the rest of the pack. Dependencies are just numpy, torch, and Pillow - this node is pure image math, no models, no downloads. The one real gotcha is the grey-background contract: it crops against #d9d9d9 specifically, so if your sheets were rendered on a different background, the detection goes sideways. Keep the background as Asset Sheet Director specifies and it just works.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| sheets | IMAGE | — | |
| row_height | INT | 51264–4096 | — |
| spacing | INT | 240–512 | — |
| padding_pct | FLOAT | 0.040–0.5 | — |
| bg_threshold | INT | 160–128 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| contact_sheet | IMAGE | — |