ImageConcatRestore
Split a contact sheet back into its original frame
- contact_image
- contact_data
- restored_image
ImageConcatRestore is the un-gluing node: it takes an image that was stitched together as a contact sheet and pulls one specific side of it back out at its original size. Specifically, it recovers the right-hand image from a two-up concatenation, which makes it the exact inverse of ComfyPanel's own ImageConcat node. Concatenate left and right images into one wide canvas, run whatever processing you need on the combined sheet, then restore the right side to its true dimensions afterward.
The trick is that nothing about "which part is the right image and how big was it" is recoverable from the pixels alone. That's the whole reason it takes a contact_data input. ImageConcat hands back a plain Python dict alongside the stitched image, and that dict is the recipe: left_width (where the right image starts), right_original_size (its true width and height), and max_height (the height of the contact sheet, used to compute the vertical centering offset). ImageConcatRestore reads that dict, crops the region to the right of left_width, and bicubically resizes it back to the original dimensions if they differ - because the contact sheet may have been processed at a different size than the source.
So the pair forms a save-then-restore round trip: ImageConcat → process the sheet → ImageConcatRestore. The two inputs are contact_image (the stitched sheet) and contact_data (that metadata dict), and the single output is restored_image. It operates over batches - it loops every image in the contact_image batch and restores each one. And it fails loudly if you hand it bad metadata: contact_data that isn't a dict raises a ValueError rather than silently producing garbage, which is the right behavior for a node whose entire correctness depends on one input.
Where you'd actually use this: any pipeline where a pair of related images (before/after, source + mask visualization, two views) needs to travel as one sheet through a processing stage that expects a single image - a preview system, an upscaler that works per-image, a ComfyPanel Photoshop round-trip - and then needs to come back apart. It's a plumbing node, unglamorous, and very much the kind of thing you only think about the day you realize your contact sheet is stuck.
One practical gotcha: contact_data is a pack-specific dict type, not a ComfyUI core type, so this node pairs with ImageConcat - you can't feed it metadata from a different pack's concat node and expect it to line up. If you're not already using ImageConcat, this node is solving a problem you don't have yet.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/Ginolazy/ComfyPanel
# restart ComfyUI
or ComfyUI Manager → "ComfyPanel". Standard pack dependencies (torch, opencv, numpy, Pillow, kornia, scipy), no model files. If restore errors out with "Invalid metadata format," you've almost certainly wired in the wrong dict - check that contact_data really came from an ImageConcat upstream, not a stray dictionary node.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| contact_image | IMAGE | — | |
| contact_data | DICT | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| restored_image | IMAGE | — |