Nodes/Ultra Tools/Ultra Tools Image + PiD
ComfyUI Node

Ultra Tools Image + PiD

One node for Krea 2, Z-Image, Anima and Qwen Image — with Nvidia's PiD upscale built in

By Yamoon-jjang·Created 14 days ago·Updated 9 days ago· 5
Ultra Tools Image + PiD
    • Original Image
    • PiD Image
    ◄positive_prompt—►
    ◄model_familyKrea 2►
    ◄diffusion_model▾►
    ◄text_encoder▾►
    ◄vae_name▾►
    ◄width1152►
    ◄height896►
    ◄batch_size1►
    ◄seed0►
    ◄steps10►
    ◄cfg1.0►
    ◄sampler_nameeuler►
    ◄schedulersimple►
    ◄denoise1.00►
    ◄negative_modezero positive conditioning►
    ◄negative_prompt►
    ◄pid_upscalefalse►
    ◄pid_model▾►
    ◄pid_samplerlcm►
    ◄pid_schedulersgm_uniform►
    ◄pid_steps4►
    ◄pid_degrade_sigma0.00►
    ◄pid_output_scale1(x4)►
    ◄sage_attentionfalse►

    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 / simple defaults, 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) or encode 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 KJ on 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.

    CategoryUltra Tools

    Inputs (24)

    NameTypeDefaultDescription
    positive_promptSTRINGConnect a STRING here. Blank text is allowed and is encoded as an empty positive prompt without rewriting.
    model_familyCOMBOKrea 24 options: Krea 2, Z-Image, Anima, Qwen Image
    diffusion_modelCOMBO1 options: <no diffusion model found>
    text_encoderCOMBO1 options: <no text encoder found>
    vae_nameCOMBO1 options: <no VAE found>
    widthINT115264–16384—
    heightINT89664–16384—
    batch_sizeINT11–16PiD ON creates a 4x target for every batch item. Batch 1 is recommended when PiD is enabled to avoid excessive VRAM use.
    seedINT00–18446744073709550000—
    stepsINT101–1000—
    cfgFLOAT1.00–100—
    sampler_nameCOMBOeuler44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
    schedulerCOMBOsimple9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
    denoiseFLOAT1.000–1—
    negative_modeCOMBOzero positive conditioning2 options: zero positive conditioning, encode negative text
    negative_promptSTRING—
    pid_upscaleBOOLEANfalseEnable integrated PiD latent upscale. PiD-only controls are shown in the frontend only when enabled.
    pid_modelCOMBO1 options: <auto PiD model>
    pid_samplerCOMBOlcm44 options: euler, euler_cfg_pp, euler_ancestral, euler_ancestral_cfg_pp, heun, heunpp2, +38
    pid_schedulerCOMBOsgm_uniform9 options: simple, sgm_uniform, karras, exponential, ddim_uniform, beta, +3
    pid_stepsINT41–1000—
    pid_degrade_sigmaFLOAT0.000–10.0 for a normal fully denoised KSampler latent; raise only for partially denoised/noisy input latents.
    pid_output_scaleCOMBO1(x4)2 options: 1(x4), 0.5(x2)
    sage_attentionBOOLEANfalseApply 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)

    NameTypeDescription
    Original ImageIMAGE—
    PiD ImageIMAGE—