Ultra Tools Image + PiD
One node for Krea 2, Z-Image, Anima and Qwen Image — with Nvidia's PiD upscale built in
- Original Image
- PiD Image
The pitch, and why it's not nonsense
The headline feature of Ultra Tools Image + PiD is the one everybody's tired of: a checkpoint loader, a text encode, a latent, a sampler and a VAE decode welded into a single node. Half the ComfyUI ecosystem ships one of those and most of them are worse than wiring five core nodes yourself.
Two things make this one worth a look anyway.
First, the model families are genuinely different from each other. Krea 2 wants clip type krea2 and a plain EmptyLatentImage. Z-Image wants lumina2, an SD3-style latent, and an AuraFlow sampling shift of 3.0. Qwen Image wants qwen_image and a shift of 3.1. Anima sits on a stable_diffusion encode. That's the kind of detail you look up once, get wrong, and spend an evening debugging - the node hardcodes the correct combination per family, so model_family is the only switch you touch.
Second, Krea 2's VAE is the weak link in an otherwise great model, and Nvidia's PiD is the community's current answer to it. PiD (PixelDiT) keeps the latent and replaces the decoder with a diffusion decoder that upsamples while it decodes - 1024×1024 in, 4096×4096 out. The KB's honest read is that PiD arguably adds detail the latent never held, so treat it as a fast upscaler rather than a faithful decoder swap. The node agrees with that read: it exposes a 1× (4× pixels) or 0.5× (2×) output scale, and it colour-matches the result back to the original with reinhard_lab automatically, which is the difference between "sharper" and "a different picture."
How the PiD stage actually runs
PiD is bound to a latent space, not to whichever model made the latent, and the source has a small registry of them: Krea 2, Anima and Qwen Image all sample in the Wan 2.1-style 16-channel/8× latent, so they share the qwenimage-token PiD checkpoint; Z-Image samples in the Flux.1 space, so it wants the flux1 checkpoint. The pid_model widget defaults to <auto PiD model> and picks the matching file itself - which is why the dropdown only shows PiD files relevant to the family you selected.
Internally the PiD pass runs at CFG 1.0 and denoise 1.0 (pid_degrade_sigma exists only for feeding it a partially denoised latent), on a 2048-token context with 512 overlap, so a 4K image is tiled rather than attempted in one shot. Defaults are 4 steps, lcm sampler, sgm_uniform - that's the fast path; it's not a second full generation.
PiD needs a text encoder: gemma_2_2b_it_elm_fp8_scaled.safetensors (or the bf16 version) in models/text_encoders/. The node finds it. If it doesn't, PiD stays off - and leaving pid_upscale false means PiD is never touched at all, so the node costs you nothing.
Inputs you'll actually set
- positive_prompt - a STRING input; wire a prompt node into it. Blank is legal and encodes as an empty positive rather than being rewritten.
- model_family / diffusion_model / text_encoder / vae_name - the four file pickers. If they read
<no diffusion model found>, your folders aren't populated the way this node expects (models/diffusion_models,models/text_encoders). - width / height - 1152×896 default, 16-pixel steps, up to 16384. These models are happiest around 1MP.
- steps / cfg / sampler_name / scheduler - 10 / 1 /
euler/simpledefaults, which is the distilled-model shape. Don't crank CFG; these families are guidance-distilled and CFG 1 is the point. - negative_mode -
zero positive conditioning(default) orencode negative text, which reveals negative_prompt. On a CFG-1 model the negative barely moves anything; that's not the node's fault. - pid_upscale, then pid_steps, pid_sampler, pid_scheduler, pid_output_scale.
- sage_attention - off by default and it means it. On uses KJNodes'
Patch Sage Attention KJon the main model only, and will error clearly if KJNodes isn't installed.
Outputs are Original Image and PiD Image. With PiD off, PiD Image just mirrors the original, so you can wire the final save to that one output and toggle PiD without rewiring. Nice touch.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/Yamoon-jjang/comfyui-Ultra-Tools
Or ComfyUI Manager → Ultra Tools. Restart, Ctrl+F5. No pip installs - the pack's requirements.txt is a comment explaining that it needs nothing beyond what ComfyUI ships with. If you have the old comfyui-Ultra-* single-purpose packs installed, delete them first; the unified pack registers the same class names, and duplicates produce genuinely baffling errors.
Traps
Batch size stays at 1 when PiD is on - the node's own tooltip says so, and it's arithmetic, not opinion: 4× resolution on top of four images is how you meet an out-of-memory error. Also don't expect PiD to fix a bad generation; it isn't a detailer. And while the pack is a one-person project with essentially no community footprint, this particular node is unusually careful - it validates the sampler/CLIP types it needs and throws a readable error instead of a stack trace.
Inputs (24)
| Name | Type | Default | Description |
|---|---|---|---|
| positive_prompt | STRING | Connect a STRING here. Blank text is allowed and is encoded as an empty positive prompt without rewriting. | |
| model_family | COMBO | Krea 2 | 4 options: Krea 2, Z-Image, Anima, Qwen Image |
| diffusion_model | COMBO | 1 options: <no diffusion model found> | |
| text_encoder | COMBO | 1 options: <no text encoder found> | |
| vae_name | COMBO | 1 options: <no VAE found> | |
| width | INT | 115264–16384 | — |
| height | INT | 89664–16384 | — |
| batch_size | INT | 11–16 | PiD ON creates a 4x target for every batch item. Batch 1 is recommended when PiD is enabled to avoid excessive VRAM use. |
| seed | INT | 00–18446744073709550000 | — |
| steps | INT | 101–1000 | — |
| cfg | FLOAT | 1.00–100 | — |
| sampler_name | COMBO | euler | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| scheduler | COMBO | simple | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 |
| denoise | FLOAT | 1.000–1 | — |
| negative_mode | COMBO | zero positive conditioning | 2 options: zero positive conditioning, encode negative text |
| negative_prompt | STRING | — | |
| pid_upscale | BOOLEAN | false | Enable integrated PiD latent upscale. PiD-only controls are shown in the frontend only when enabled. |
| pid_model | COMBO | 1 options: <auto PiD model> | |
| pid_sampler | COMBO | lcm | 44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38 |
| pid_scheduler | COMBO | sgm_uniform | 9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3 |
| pid_steps | INT | 41–1000 | — |
| pid_degrade_sigma | FLOAT | 0.000–1 | 0.0 for a normal fully denoised KSampler latent; raise only for partially denoised/noisy input latents. |
| pid_output_scale | COMBO | 1(x4) | 2 options: 1(x4), 0.5(x2) |
| sage_attention | BOOLEAN | false | Apply KJ Patch Sage Attention KJ to the main generation MODEL only. OFF has zero KJ/Sage runtime dependency; ON uses auto with allow_compile disabled. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| Original Image | IMAGE | — |
| PiD Image | IMAGE | — |