Nodes/comfyui-obvpm/Load Images & Compose (obvpm)
ComfyUI Node

Load Images & Compose (obvpm)

Turn several references into one frame

By chanon·Created about a month ago·Updated a day ago· 40
Load Images & Compose (obvpm)
    • image
    layers[]
    max_megapixels1.00
    gap0
    backgroundblack

    This one exists because of a specific annoyance in modern reference-driven generation. The models that consume references - the in-context editors, the reference-to-video pipelines - increasingly want several images: a face, an outfit, a location, a prop. But the input you actually feed them is often a single frame, which leaves you building a collage in an image editor, re-uploading it, and doing it again when you pick a different prop.

    Load Images & Compose is that collage, built on the node. Several input images, each with its own crop, packed into one image within a megapixel budget, with the layers visible while you work.

    How it works

    The node's body is a layer strip on the left and a main view on the right. Adding a layer: the + add image button, the add dropdown (a live listing of your input folder, subfolders included), dropping image files onto the node, or pasting from the clipboard while it's selected. Cards dragged in from the Artius browser work too - one already in the input folder is referenced in place rather than copied.

    Each layer keeps its own crop, drawn exactly like the pack's Load Image & Crop: drag to draw, drag inside to move, drag a corner to resize, click outside to clear. Crops are stored in normalized coordinates, so they survive reloads and mean the same thing if the source changes size. Each layer also has an aspect lock - a pill in the crop view that pins the crop to 16:9, 1:1, 4:5 and so on, independently per layer, with free as the default. With a ratio set and no crop drawn, a dashed rectangle shows the largest centred cut of that ratio, which is what actually gets composed.

    The first entry in the strip is Result: the real composition, at the real aspect ratio, each slot labelled with its pixel size. Clicking a slot jumps to that layer's crop editor.

    The layout rules, which are the interesting part

    The packer is opinionated and the opinions are the reason to use it rather than a grid.

    Layers keep their order, their exact aspect ratio, and their relative pixel sizes. Every layer is scaled by the same factor, and none is ever enlarged. So a small crop sitting next to a large one comes out small in area, because that's what it is - you can't stretch a 256px face reference into the space a 3000px one could have used, and the packer won't invent pixels to fill a slot. Nothing is ever rotated either; the quarter-turn a texture atlas would take for free is off the table, because a rotated reference is a wrong reference.

    That makes max_megapixels a cap, not a target. Four 256×256 crops compose to a 512×512 sheet however generous your budget, and the node doesn't apologise for it. Set it to 0 for no cap at all.

    To pick the row breaks it sweeps 48 candidate widths across four placement orders - your layer order, then tallest-first, widest-first and largest-first - and only displaces your order if another packs at least three points tighter. Dragging layers around still means something. The info line under the preview names the order it used and how full the sheet came out, something like 4 layers → 1104 × 928 · 0.98 MP · 92% filled.

    The settings that matter

    • max_megapixels (default 1.0) - the largest the result may be. 1.0 = 1024×1024. Sides get rounded to a multiple of 16.
    • gap (default 0) - pixels of background between layers. Zero puts them flush. A few pixels genuinely helps a model tell one reference from the next rather than reading the sheet as one weird photo, and it's the single setting I'd change first.
    • background - black, grey or white. It shows in the gaps and in the up-to-16-pixel margin the rounding leaves.

    The only output is image. Wire it into whatever wants a single reference frame. Changing any crop, or the file behind any layer, causes a re-execution on the next run.

    Practical notes and limits

    The layer list lives in a hidden JSON widget managed entirely by the frontend, so don't hand-edit it - a half-written value is tolerated, but the editor is the interface. Up to 64 layers, with hard sanity caps on dimensions and file size on the server side. If the pack's JavaScript doesn't load, you can't edit layers at all; that's the cost of a node this visual.

    Install

    Manager, search comfyui-obvpm, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/chanon/comfyui-obvpm
    

    Restart ComfyUI. No Python dependencies to install - the pack declares none deliberately, since everything it imports (torch, numpy, PIL) already ships with ComfyUI - and no models to download. This node's editor is JavaScript, so a hard browser refresh after a pack update is worth doing if the canvas looks stale.

    Categoryobvpm/image

    Inputs (4)

    NameTypeDefaultDescription
    layersSTRING[]Managed by the layer editor on the node — no need to edit by hand.
    max_megapixelsFLOAT1.000–128Largest the composed image may be (1.0 = 1024x1024 pixels). A CAP, not a target: every layer is scaled by one shared factor and none is ever enlarged, so a sheet of small images comes out small rather than being blown up to fill this. 0 = no cap: every layer at its own size (in fill sizing, a sheet of the sources' total area). Sides are rounded to a multiple of 16.
    gapINT00–256Pixels of background between layers. 0 puts them flush against each other; a few pixels helps a model tell one reference from the next.
    backgroundCOMBOblackColour behind the layers — seen in the gaps, and in the up-to-16-pixel margin left by rounding.

    Outputs (1)

    NameTypeDescription
    imageIMAGEThe composed sheet, one image containing every layer.