pre_ZImageInpaint_patch
Z-Image's union ControlNet, wired for masked inpainting
- context
- image
- latent_image
- latent_mask
- context
- model
- positive
- negative
- latent
Z-Image is the best-served base for ControlNet right now - Alibaba PAI shipped a union checkpoint (canny, depth, pose, and more) for it within about a week of release, and that union carries its own inpaint mode alongside the usual conditioning types. This node is a preset built around exactly that combo: it loads the union ControlNet, patches your model with it, and stitches in a masked-latent inpaint pass in one place. Its controlnet dropdown even defaults to Z-Image-Turbo-Fun-Controlnet-Union-2.1.safetensors - the actual Alibaba PAI union file - so the node is opinionated about which checkpoint you're meant to use, not a generic loader.
How it works
Wire in an image and the ControlNet condition it represents (canny map, depth map, whatever you preprocessed), plus latent_image/latent_mask for the region you want regenerated. The node patches your model with the union checkpoint at the given strength, builds inpaint-aware positive/negative conditioning around the masked latent, and can optionally route the whole thing through differential diffusion if diffDiffusion is on. Differential diffusion changes what a mask means: instead of a hard binary "regenerate this / leave this alone" boundary, each pixel's mask value sets roughly when during denoising that pixel starts changing, so edges blend rather than seam. It's the modern answer to the old mask-blur trick, and it's on by default here.
The inputs and outputs that matter
context(required) - the pack's run-context bundle.image(optional) - your ControlNet conditioning image.controlnet(optional, defaultZ-Image-Turbo-Fun-Controlnet-Union-2.1.safetensors) - which ControlNet checkpoint to load and patch with.strength(default 0.8, range 0–2) - control weight. That default sits right at the top of Alibaba PAI's own recommended range for their unions (0.65–0.8), so treat 0.8 as roughly the ceiling of "sane," not a conservative starting point - the old SD 1.5 habit of pushing toward 1.0+ overcooks these newer union checkpoints.latent_image/latent_mask(optional) - the region to inpaint. Notelatent_imageis typed IMAGE in this node despite the name, so it wants an image, not a pre-encoded latent.diffDiffusion(default true) - toggles the smooth-mask-boundary behavior described above.smoothness(default 0, range 0–1000) - an additional edge-softening knob on top of whateverdiffDiffusionis doing; the wide range suggests it's measured in something like pixels rather than a 0–1 fraction.- Outputs:
contextpassthrough,model(patched),positive/negative(CONDITIONING), andlatent.
How to install it
Search ComfyUI-Apt_Preset in ComfyUI Manager, or clone it manually:
cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_Preset.git
install.bat covers Windows dependencies; on Linux or Mac, read the script and run its pip installs yourself, or let ComfyUI Manager resolve what's missing on first load. The ControlNet checkpoint isn't bundled - download Z-Image-Turbo-Fun-Controlnet-Union-2.1.safetensors (or whichever Z-Image union you're using) from Alibaba PAI's release and drop it in ComfyUI/models/controlnet, or the dropdown will come up empty.
Common issues & troubleshooting
controlnet dropdown shows nothing to select. The default filename is just a suggestion baked into the node - it doesn't auto-download. Fetch the actual checkpoint and restart ComfyUI.
Inpainted region has a visible seam despite diffDiffusion being on. Push smoothness up before disabling anything - it's meant to layer on top of the differential-diffusion edge behavior, not replace it. If seams persist at high smoothness, check latent_mask itself for hard edges; a mask with genuine antialiasing on its border gives differential diffusion more to work with than a pure binary mask.
Results look overcooked or lose the ControlNet's own detail entirely. You're likely stacking strength too high for a union checkpoint - walk it down toward 0.6–0.7 rather than the top of the slider, especially if you're also running other conditioning through the same context.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| context | RUN_CONTEXT | — | |
| imageopt | IMAGE | — | |
| controlnetopt | COMBO | Z-Image-Turbo-Fun-Controlnet-Union-2.1.safetensors | 1 options: None |
| strengthopt | FLOAT | 0.800–2 | — |
| latent_imageopt | IMAGE | — | |
| latent_maskopt | MASK | — | |
| diffDiffusionopt | BOOLEAN | true | — |
| smoothnessopt | INT | 00–1000 | — |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| context | RUN_CONTEXT | — |
| model | MODEL | — |
| positive | CONDITIONING | — |
| negative | CONDITIONING | — |
| latent | LATENT | — |