TS Multi Reference
Three reference images into the conditioning stream, one node
- conditioning
- vae
- image_1
- mask_1
- image_2
- mask_2
- image_3
- mask_3
- image_1
- image_2
- image_3
- conditioning
Multi-reference pipelines - Qwen-Image-Edit, Flux-with-references - want you to attach one or more reference images to the conditioning stream as reference_latents, so the model has a picture (or three) to work from alongside the text. Do it by hand and it's a small wall of nodes: three VAE Encode, three Reference Latent, all wired into the right sockets. TS MultiReference collapses that into one node: up to three images in, one conditioning out, with the sizing and encoding handled for you.
How it works
For each connected image_N, the node resizes the image down to a megapixel budget (max_megapixels, 1.0 default), snaps the dimensions to a grid (divide_by, 32 default - a safe choice for Flux 2 and Qwen-Image-Edit; most VAEs only need 8 or 16), VAE-encodes it, and appends it as a reference_latent on your conditioning. If a source's aspect doesn't snap cleanly to the grid, a thin band is center-cropped off the longer side so the output aspect always matches and the picture is never stretched.
The conditioning and vae inputs are both optional - the node only runs the VAE encode when both images and conditioning are connected. Connect images alone and it just resizes them for you, which is handy on its own.
There's a genuinely thoughtful piece of plumbing with the masks: mask_1..3 are used only as a bounding-box hint (with 16 px padding) - the pixels inside the box are preserved as-is, the mask shape is not cut out. And mask_orientation auto-detects from the four corners whether your mask means "1.0 = transparent" (ComfyUI Load Image alpha) or "1.0 = subject" (SAM/BiRefNet outputs), so both conventions just work. If a full-bleed subject covers the corners and the auto-detection guesses wrong, set it explicitly.
The input you'll actually set
max_megapixels- how big each reference gets before encoding. 1.0 is right for most pipelines; lower saves VRAM, higher keeps more detail.divide_by- the alignment grid. Leave 32 unless you know your model wants something else (e.g. 56/112 for Qwen).block_empty_slots- this one's the quiet trap. On by default, so an empty slot returns an ExecutionBlocker and downstream nodes (Save Image, PreviewImage) are skipped rather than run with a blank. Turn it off when you want empty slots to passNoneso downstream nodes with optional IMAGE inputs keep running.
The outputs mirror the inputs: image_1..3 (the resized references, blocker-or-None when a slot is empty) and conditioning (your input with one reference_latent appended per connected image).
Install
No extra dependencies - it's a pure-Python conditioning utility inside comfyui-timesaver.
cd ComfyUI/custom_nodes
git clone https://github.com/AlexYez/comfyui-timesaver
cd comfyui-timesaver
python -m pip install -r requirements.txt
Common issues
- "Nothing generates." Check
block_empty_slots- if an empty slot is blocking the branch, that's it doing exactly what it says. - "Reference looks wrong/cropped." If a thin band was cropped to fit the grid, that's by design (never stretched). And if the mask bbox landed on the wrong region, fix
mask_orientation. - "Doesn't work with my model." It only does two things - resize and VAE-encode - so it works with whatever model accepts
reference_latentsin its conditioning. If your model doesn't, this node won't make it.
The one honest caveat: this is scaffolding, not magic. It removes the tedious encode wiring from multi-reference workflows - the model still has to know what to do with the references, which is a Qwen-Edit / Flux-reference capability, not something this node provides.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| max_megapixels | FLOAT | 1.000.01–16 | Maximum size for each reference image before VAE encoding. |
| divide_by | INT | 321–128 | Resized dimensions are an exact multiple of this value before VAE encoding. Most VAEs need 8 or 16; the default 32 is a safe choice for Flux 2, Qwen image edit, etc. If the source aspect does not snap exactly to the grid, a thin band is center-cropped off the longer side so the output aspect always matches and the image is never stretched. |
| block_empty_slots | BOOLEAN | true | When enabled (default), empty image_N slots return ExecutionBlocker so downstream nodes are silently skipped (e.g. Save Image / PreviewImage). Disable to pass None on empty slots instead, so downstream nodes with optional IMAGE inputs (like TS Resolution Selector) keep running and apply their own fallback. |
| conditioningopt | CONDITIONING | Conditioning that will receive reference_latents. Optional: when not connected, the node skips VAE encoding and only resizes images for multi_images. | |
| vaeopt | VAE | VAE used to encode reference images into latents. Required only when both images and conditioning are connected. | |
| image_1opt | IMAGE | Reference image 1. Connect any IMAGE source. | |
| mask_1opt | MASK | Optional MASK for image_1. Used ONLY as a bounding-box hint with 16 px padding — pixels inside the bbox are preserved as-is (the mask shape is NOT cut out). The mask is binarised at 0.5 and its orientation is auto-detected from the four corners, so both ComfyUI Load Image alpha (1.0=transparent) and segmentation outputs (1.0=subject, e.g. SAM, BiRefNet, RemBG, Mask Editor) are handled correctly without any toggles. | |
| image_2opt | IMAGE | Reference image 2. Connect any IMAGE source. | |
| mask_2opt | MASK | Optional MASK for image_2. See mask_1 tooltip. | |
| image_3opt | IMAGE | Reference image 3. Connect any IMAGE source. | |
| mask_3opt | MASK | Optional MASK for image_3. See mask_1 tooltip. | |
| mask_orientationopt | COMBO | auto | How to read the MASK inputs. auto = 4-corner voting (works for typical photos, can guess wrong on full-bleed subjects that cover the corners). Pick an explicit convention if the crop lands on the wrong region. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image_1 | IMAGE | Resized version of image_1 (ExecutionBlocker or None when the slot is empty). |
| image_2 | IMAGE | Resized version of image_2 (ExecutionBlocker or None when the slot is empty). |
| image_3 | IMAGE | Resized version of image_3 (ExecutionBlocker or None when the slot is empty). |
| conditioning | CONDITIONING | Input conditioning with one reference_latent appended per connected image. |