Nodes/ComfyUI-EditUtils/EditUtils: QwenImage 2.1 Config Preparer lrzjason
ComfyUI Node

EditUtils: QwenImage 2.1 Config Preparer lrzjason

One Ticket Per Reference Image

By lrzjason·Created 8 months ago·Updated 3 days ago· 234
EditUtils: QwenImage 2.1 Config Preparer lrzjason
  • image
  • configs
  • mask
  • configs
  • config
to_reftrue
ref_main_imagetrue
ref_longest_edge1024
ref_croppad
ref_upscalelanczos
to_vltrue
ref_resize_modelongest_edge
rope_x_offset0
rope_y_offset0

A node that writes tickets instead of tensors

ComfyUI-EditUtils doesn't put its settings on the encode node. It builds a small list of dictionaries - one per image - and the encode node reads that list. QwenImage21ConfigPreparer_EditUtils writes exactly one entry into that list: this image, at this size, is a reference (or isn't), is the main image whose latent you sample from (or isn't), goes to the vision tower (or doesn't), and sits at this spot on the canvas.

On its own it computes nothing you can see. Chain three of them and you've described three references; chain eight and you've described eight - which is the real reason this node exists, since the pack's one-piece QwenImage21EditTextEncode_EditUtils stops at three images. The chain path has no cap.

Context, briefly: Qwen-Image-Edit is the model that made a whole adapter stack unnecessary - reference conditioning arrives as an image plus a plain-language instruction, no mask, no ControlNet, no IP-Adapter. 2.1 keeps that shape but changes the plumbing: prompt and references are encoded together by a Qwen3-VL text encoder, and each reference latent gets spliced into the text sequence at the encoder's vision slots. That's what the fields below are serving.

The mechanism the fields are serving

The encode node downstream does the work: it scales each image toward ref_longest_edge, snaps it to a multiple of 32 pixels, pads it to the VAE grid, encodes it, and hangs the resulting latents on the conditioning under reference_latents (plus the rope offsets under reference_rope_offsets). Qwen-Image 2.1's VAE is 64-channel with 16x spatial downscale, so 32 pixels is 16 × 2 - one vision slot maps onto a 2×2 group of latent tokens. Get that alignment wrong and the vision tower and the diffusion model are talking about different pixels.

That's why ref_longest_edge steps in 32s. Don't fight it.

The fields a beginner actually touches

  • image - the reference (or the main image; same input either way).
  • configs - the chain. Leave it empty on the first node, wire the previous node's configs output into it for every one after.
  • ref_main_image - the image whose padded latent becomes the sampling start latent. Exactly one node in the chain should have it on.
  • ref_longest_edge - 1024 to start. Bigger refs aren't automatically better; you're paying tokens for them.
  • to_vl - the author's tooltip says keep it enabled for trained behaviour, and the source agrees: with it off you're splicing a reference where the model was never trained to see one.

The rest are for when something is wrong: ref_crop (pad/center/disabled), ref_upscale (lanczos by default), ref_resize_mode (longest_edge matches ref_longest_edge to the long side; area matches total pixels to its square - a portrait and a landscape then cost the same), mask, and rope_x_offset / rope_y_offset, which only do anything if you also put QwenImage21EditApply_EditUtils in the graph.

Outputs

Two, and they're the same information: configs is the whole accumulated list - wire it to the next preparer or into the encode node's configs input. config is just this image's own dict, useful when you want to inspect it or hand a single entry to another node.

Install

ComfyUI Manager, search ComfyUI-EditUtils; or:

cd ComfyUI/custom_nodes
git clone https://github.com/lrzjason/ComfyUI-EditUtils

Restart ComfyUI. There's no requirements.txt here - the pack is plain Python over ComfyUI, so nothing extra gets pip-installed. The real dependency is your ComfyUI build: it needs upstream Qwen-Image 2.1 (qwen_image21) support. On an older build the model won't load at all. The example workflow loads qwen_image_2.1_int8_convrot.safetensors through UNETLoader, qwen3vl_8b_fp8_scaled.safetensors through CLIPLoader with type qwen_image, and qwen_image_2.1_vae_bf16.safetensors through VAELoader.

Where people get burned

to_vl=True together with to_ref=False looks like a sensible combo and isn't: the encoder forces to_ref back on and prints a note, because a vision slot with no latent behind it breaks the alignment. Set to_vl off if you want that image excluded from the references.

Two main images is a silent no-op - the second one's ref_main_image is forced to False, and if you set none at all the first image gets picked for you with a console note. Same shape of gotcha with mask: if its height and width don't match the image, it gets dropped and the run continues unmasked.

Finally, all-zero rope offsets are the native path, not a bug. If you wired the offsets expecting them to do something and nothing moved, check that the Edit Apply patch is actually in the graph.

Categoryadvanced/conditioning

Inputs (12)

NameTypeDefaultDescription
imageIMAGE
configsoptLISTConfigs list
to_refoptBOOLEANtrueAdd image to reference latent
ref_main_imageoptBOOLEANtrueSet image as main image which would return the latent as output.
ref_longest_edgeoptINT102432–4096Reference target size. Snapped to 32-pixel multiples (vision slot <-> 2x2 latent group alignment).
ref_cropoptCOMBOpadCrop method for reference image
ref_upscaleoptCOMBOlanczosUpscale method for reference image
to_vloptBOOLEANtrueFeed the resized reference to the Qwen3-VL text encoder and splice its latent at the vision slot. Keep enabled for trained behavior.
maskoptMASK
ref_resize_modeoptCOMBOlongest_edgelongest_edge: scale so the longest dimension equals ref_longest_edge. area: scale so total pixels equals ref_longest_edge squared.
rope_x_offsetoptINT00–4096ROPE horizontal position offset in pixels (32-aligned). Shifts reference rightward on the canvas. Requires QwenImage21EditApply_EditUtils.
rope_y_offsetoptINT00–4096ROPE vertical position offset in pixels (32-aligned). Shifts reference downward on the canvas. Requires QwenImage21EditApply_EditUtils.

Outputs (2)

NameTypeDescription
configsLIST
configANY