Generated reference · ComfyUI workflow · heavy-image

Qwen-Image InstantX Control

Qwen-Image 2512 (bf16) steered by the InstantX ControlNets, SFW only, in two modes: union (generate from a prepared control map) and inpaint (repaint the white region of a mask). Renders on the RunPod VIDEO endpoint and bills the video …

heavy-image26nodesGPU H100out image~296sv1.0.0

On this page

Qwen-Image 2512 (bf16) steered by the InstantX ControlNets, SFW only, in two modes: union (generate from a prepared control map) and inpaint (repaint the white region of a mask). Renders on the RunPod VIDEO endpoint and bills the video ledger while returning a still (heavy-image, A.02.05). union is translated from Comfy-Org/workflow_templates@aaac56dd templates/image_qwen_image_instantx_controlnet.json: FluxKontextImageScale on the control image, ControlNetApplyAdvanced (strength 1, start 0, end 1, with the VAE) on the prompt and an empty negative, the latent VAE-encoded from the scaled control image, ModelSamplingAuraFlow 3.1, KSampler euler/simple. That template samples at 4 steps and CFG 1 only because it applies the Lightning 4-step LoRA, which has no manifest row, so this graph uses the family's no-LoRA values, 20 steps at CFG 2.5 (see sampler_note). Its Lotus depth preprocessor has no manifest rows either, so the graph takes a ready map. inpaint is translated from templates/image_qwen_image_instantx_inpainting_controlnet.json without its bypassed outpaint branch and LoRA: ImageScaleToMaxDimension (area, 1536), the Grow and Blur Mask chain (GrowMask 0 tapered, ImageBlur 31/1), SetLatentNoiseMask, ControlNetInpaintingAliMamaApply (1, 0, 1), KSampler euler/simple 20 steps CFG 2.5, a single-space negative, and ImageCompositeMasked over the scaled source as the output. The mask is a separate black-and-white image (white = repaint) rather than the template's MaskEditor alpha. Both templates load the original Qwen-Image transformer (qwen_image_fp8_e4m3fn); the volume carries Qwen-Image 2512 bf16, the same architecture.

26Graph nodes
21Node classes
12Inputs
5Models

Tags: heavy-imagerunpod-serverlessvolume-backedimage-to-imagecontrolnetinpaintqwen-image

Inputs (12)#

The typed parameter surface callers bind when they request this workflow. Enum options and numeric bounds are the values the workflow document declares.

promptstringrequireddefault Post-apocalyptic style clothing, long wavy hair, rough texture, exotic woman, tattered coarse-woven linen fabric, wearing a hood, mechanical aesthetics, mainly in dark gray tones, low-saturation earthy yellow, sense of impact and rebellion, doomsday aesthetics, grotesque aesthetics, works of art, backlighting, film photography, professional photography works, clear visible face, emotional and atmospheric dynamic photography, Fujichrome color positive film, shot with a 17mm Hasselblad ultra-wide-angle lens, f/1.2 large aperture, side backlighting, artistic light, hair light, Rembrandt light, 8K high-definition image quality, delicate real human skin texture.
Positive prompt in natural prose. The default is the union template's; the inpainting template's example is "The Queen, on a throne, surrounded by Knights, HD, Realistic, Octane Render, Unreal engine". In union mode describe what the control map shows: on 2026-09-14 the default portrait prompt over a full-length figure's canny map ignored the map (A.05.02).
negative_promptstringdefault
Negative prompt, honoured at CFG above 1. Left empty it becomes each template's own negative: empty for union, a single space for inpaint.
modeenumdefault union
union = generate from control_image (a depth, canny, soft-edge or pose map; the output takes its size, scaled by FluxKontextImageScale to about 1 MP) through the InstantX Union ControlNet. inpaint = repaint the white region of mask_image over source_image through the InstantX Inpainting ControlNet, compositing the result back over the source.
options: unioninpaint
control_imageimage
union only, and required there: a ready control map. The union template derives one with Lotus depth, which the volume does not carry, so no preprocessor runs in this graph. A union job without it is refused when the graph is rendered.
source_imageimage
inpaint only, and required there: the image to repaint, scaled so its long side is 1536 px (area), as the template does. The output takes that size.
mask_imageimage
inpaint only, and required there: black and white, the same aspect as source_image; white is repainted (read from the red channel).
control_strengthfloatdefault 1.0min 0.0max 2.0
ControlNet strength (1 in both templates; the node accepts up to 10, capped here at 2). The start and end percents stay at the templates' 0 and 1.
mask_growintegerdefault 0min 0max 64
inpaint only: pixels the mask grows before blurring (the template's Grow and Blur Mask expand, 0).
mask_blur_radiusintegerdefault 31min 1max 31
inpaint only: blur radius that feathers the mask edge (the template's value, 31, the node's maximum).
stepsintegerdefault 20min 1max 60
Sampling steps (20: the inpainting template's value without the 4-step LoRA; see the description for union).
cfgfloatdefault 2.5min 1.0max 10.0
Classifier-free guidance (2.5: the inpainting template's value without the 4-step LoRA).
seedintegerdefault -1
Random seed (-1 = random)

ComfyUI node graph (26)#

The executable ComfyUI prompt graph: 26 nodes across 21 distinct node classes, wired by 33 data dependencies. Nodes tinted green come from a custom node pack this workflow declares; the rest are ComfyUI core / baked-community classes.

flowchart TD n0["1: UNETLoader"] n1["2: CLIPLoader"] n2["3: VAELoader"] n3["4: ModelSamplingAuraFlow"] n4["5: CLIPTextEncode"] n5["6: CLIPTextEncode"] n6["7: ControlNetLoader"] n7["10: LoadImage"] n8["11: FluxKontextImageScale"] n9["12: VAEEncode"] n10["13: ControlNetApplyAdvanced"] n11["20: LoadImage"] n12["21: ImageScaleToMaxDimension"] n13["22: LoadImage"] n14["23: ImageToMask"] n15["24: GrowMask"] n16["25: MaskToImage"] n17["26: ImageBlur"] n18["27: ImageToMask"] n19["28: VAEEncode"] n20["29: SetLatentNoiseMask"] n21["30: ControlNetInpaintingAliMamaApply"] n22["40: KSampler"] n23["41: VAEDecode"] n24["42: ImageCompositeMasked"] n25["43: SaveImage"] n0 -->|model| n3 n1 -->|clip| n4 n1 -->|clip| n5 n7 -->|image| n8 n8 -->|pixels| n9 n2 -->|vae| n9 n4 -->|positive| n10 n5 -->|negative| n10 n6 -->|control_net| n10 n8 -->|image| n10 n2 -->|vae| n10 n11 -->|image| n12 n13 -->|image| n14 n14 -->|mask| n15 n15 -->|mask| n16 n16 -->|image| n17 n17 -->|image| n18 n12 -->|pixels| n19 n2 -->|vae| n19 n19 -->|samples| n20 n18 -->|mask| n20 n4 -->|positive| n21 n5 -->|negative| n21 n6 -->|control_net| n21 n2 -->|vae| n21 n12 -->|image| n21 n18 -->|mask| n21 n3 -->|model| n22 n22 -->|samples| n23 n2 -->|vae| n23 n12 -->|destination| n24 n23 -->|source| n24 n18 -->|mask| n24
Data-flow DAG — scroll to zoom, drag to pan.

Nodes (26)#

1UNETLoadercore
unet_name = qwen_image_2512_bf16.safetensorsweight_dtype = default
outputs: MODEL
2CLIPLoadercore
clip_name = qwen_2.5_vl_7b.safetensorstype = qwen_imagedevice = default
outputs: CLIP
3VAELoadercore
vae_name = qwen_image_vae.safetensors
outputs: VAE
4ModelSamplingAuraFlowcore
model = ◂ node 1 · out[0]shift = 3.1
outputs: MODEL
5CLIPTextEncodecore
text = {{constructed_prompt}} tmplclip = ◂ node 2 · out[0]
outputs: CONDITIONING
6CLIPTextEncodecore
text = {{negative_prompt or mode_profile[mode].negative}} tmplclip = ◂ node 2 · out[0]
outputs: CONDITIONING
7ControlNetLoadercore
control_net_name = {{mode_profile[mode].controlnet}} tmpl
outputs: CONTROL_NET
10LoadImagecore
image = {{control_image}} tmpl
outputs: IMAGEMASK
11FluxKontextImageScalecore
image = ◂ node 10 · out[0]
outputs: IMAGE
12VAEEncodecore
pixels = ◂ node 11 · out[0]vae = ◂ node 3 · out[0]
outputs: LATENT
13ControlNetApplyAdvancedcore
positive = ◂ node 5 · out[0]negative = ◂ node 6 · out[0]control_net = ◂ node 7 · out[0]image = ◂ node 11 · out[0]vae = ◂ node 3 · out[0]strength = {{control_strength}} tmplstart_percent = 0.0end_percent = 1.0
outputs: CONDITIONINGCONDITIONING
20LoadImagecore
image = {{source_image}} tmpl
outputs: IMAGEMASK
21ImageScaleToMaxDimensioncore
image = ◂ node 20 · out[0]upscale_method = arealargest_size = 1536
outputs: IMAGE
22LoadImagecore
image = {{mask_image}} tmpl
outputs: IMAGEMASK
23ImageToMaskcore
image = ◂ node 22 · out[0]channel = red
outputs: MASK
24GrowMaskcore
mask = ◂ node 23 · out[0]expand = {{mask_grow}} tmpltapered_corners = true
outputs: MASK
25MaskToImagecore
mask = ◂ node 24 · out[0]
outputs: IMAGE
26ImageBlurcore
image = ◂ node 25 · out[0]blur_radius = {{mask_blur_radius}} tmplsigma = 1.0
outputs: IMAGE
27ImageToMaskcore
image = ◂ node 26 · out[0]channel = red
outputs: MASK
28VAEEncodecore
pixels = ◂ node 21 · out[0]vae = ◂ node 3 · out[0]
outputs: LATENT
29SetLatentNoiseMaskcore
samples = ◂ node 28 · out[0]mask = ◂ node 27 · out[0]
outputs: LATENT
30ControlNetInpaintingAliMamaApplycore
positive = ◂ node 5 · out[0]negative = ◂ node 6 · out[0]control_net = ◂ node 7 · out[0]vae = ◂ node 3 · out[0]image = ◂ node 21 · out[0]mask = ◂ node 27 · out[0]strength = {{control_strength}} tmplstart_percent = 0.0end_percent = 1.0
outputs: CONDITIONINGCONDITIONING
40KSamplercore
model = ◂ node 4 · out[0]seed = {{seed}} tmplsteps = {{steps}} tmplcfg = {{cfg}} tmplsampler_name = eulerscheduler = simplepositive = {{mode_profile[mode].positive}} tmplnegative = {{mode_profile[mode].negative_ref}} tmpllatent_image = {{mode_profile[mode].latent}} tmpldenoise = 1.0
outputs: LATENT
41VAEDecodecore
samples = ◂ node 40 · out[0]vae = ◂ node 3 · out[0]
outputs: IMAGE
42ImageCompositeMaskedcore
destination = ◂ node 21 · out[0]source = ◂ node 41 · out[0]x = 0y = 0resize_source = falsemask = ◂ node 27 · out[0]
outputs: IMAGE
43SaveImagecore
images = {{mode_profile[mode].output}} tmplfilename_prefix = isis/qwen-edit-control

Prompt construction#

template
{base_prompt}

Variables (1)#

base_prompt
{{prompt}} tmpl

Parameter banks (2)#

The prompt / configuration lookup tables this workflow keys into from its inputs — the vocabulary that turns a style / palette / preset selection into graph parameters.

mode_profile (2)#

union
{"controlnet": "Qwen-Image-InstantX-ControlNet-Union.safetensors", "negative": "", "positive": ["13", 0], "negative_ref": ["13", 1], "latent": ["12", 0], "output": ["41", 0]}
inpaint
{"controlnet": "Qwen-Image-InstantX-ControlNet-Inpainting.safetensors", "negative": " ", "positive": ["30", 0], "negative_ref": ["30", 1], "latent": ["29", 0], "output": ["42", 0]}

requires_families (2)#

qwen-imageqwen-image-control

Models & dependencies#

Models required (5)#

qwen_image_2512_bf16.safetensors
qwen_2.5_vl_7b.safetensors
qwen_image_vae.safetensors
Qwen-Image-InstantX-ControlNet-Union.safetensors
Qwen-Image-InstantX-ControlNet-Inpainting.safetensors

Output contract#

What a successful run of this workflow returns.

type
image
format
png

Taxonomy & routing#

How the control plane classifies this workflow — from the committed workflow-taxonomy-registry.json. It drives the consistency / control surface the agentic director can exercise over the workflow.

assetFamily
portrait-hero-image-bundle
outputPackageProfile
image-single-profile
controlModalities
controlnet-depthcontrolnet-inpaintmodel-locksampler-scheduler-lockseed-lock
consistencyDimensions
identitylightingenvironment
notes
Qwen-Image 2512 with the InstantX union ControlNet (from a prepared control map) or inpainting ControlNet (mask, composited back), a still rendered on the RunPod video endpoint (heavy-image), SFW only.