Nodes/EmberFrame Nodes/EmberFrame Normalize ZImage/Flux Latent
ComfyUI Node

EmberFrame Normalize ZImage/Flux Latent

The adapter that keeps PiD from warping your Z-Image latent

By emberframe·Created 3 months ago·Updated 3 months ago· 0
EmberFrame Normalize ZImage/Flux Latent
  • latent
  • latent
  • info
directioncomfy_to_pid
scale_factor0.3611
shift_factor0.1159

If you're here, the PiD output is probably warped, smeared, or just wrong, and this is the node that fixes it. PiD - NVIDIA's Pixel Diffusion Decoder - doesn't live in Comfy's latent space. It treats latent-to-image decoding as conditional pixel diffusion, merging decode and upscale into one step, and it was trained on latents with a different scale and offset than the ones your Z-Image or Flux sampler actually writes. Shove a raw Comfy latent into PiD Decode and you're feeding the model numbers it never saw in training. Garbage in, garbage out, at 4x resolution.

This node is a two-line affine transform sitting between your sampler and PiD. In one direction it rescales Comfy latents into PiD's range; in the other it maps them back. That's the whole job, and it does it without touching model weights or calling anything external.

The mechanism

The math is (samples - shift) * scale for comfy_to_pid, and the inverse (samples / scale) + shift for pid_to_comfy. The defaults - scale_factor 0.3611, shift_factor 0.1159 - are the values the EmberFrame author calibrated for their Z-Image Base / Turbo workflows, and they're the numbers you should keep. The README's known-good setup is direction comfy_to_pid with exactly those two values on the final latent.

The info output is worth a glance: it prints the formula it applied plus min/max/mean/std of the latent before and after. When something downstream looks off, that string tells you instantly whether the transform actually ran.

Inputs and outputs that matter

Only two widgets are worth touching:

  • direction - comfy_to_pid (default) for feeding PiD Decode, pid_to_comfy if you're going back into a Comfy sampler after a PiD pass.
  • latent - wire this from your sampler's output (see the gotcha below about which one).

Leave scale_factor and shift_factor at 0.3611 / 0.1159 unless you have a reason not to. They're per-backbone values, and for Z-Image/Flux these are the known-good ones.

Outputs: latent (the transformed LATENT, goes into PiD Decode) and info (STRING diagnostics).

Installing it

This is part of the EmberFrame Nodes pack, so install once:

cd ComfyUI/custom_nodes
git clone https://github.com/emberframe/emberframe-nodes.git

Then restart Comfy. Or use ComfyUI Manager and search "EmberFrame Nodes". No pip deps, no bundled models - but the PiD nodes themselves (PiD Decode, PiD Prepare) come from the separate ComfyUI-PiD pack by Merserk, which auto-downloads the NVIDIA PiD checkpoints. You need both.

Where people get burned

  • Only normalize the right latent. The README is explicit: if you feed the sampler's output, denoised_output, or a captured final_latent into PiD, normalize it first. But if you feed the callback x directly (the sampler's internal state), test without normalization - callback x is already in the sampler/model latent space and double-normalizing will break it.
  • Scale is not negotiable. For Z-Image/Flux, PiD is a 4x decoder - both the 2k and 2kto4k checkpoints are 4x. Running PiD Decode at scale 1 or 2 produces exactly the warped, distorted output you're probably googling. Keep scale = 4 and the 2k checkpoint if you want roughly 1088×1920 out of a ~272×480 generation.
  • pid_to_comfy with a zero scale throws a clear error, so you can't silently blow up the math backwards.
CategoryEmberFrame/PiD

Inputs (4)

NameTypeDefaultDescription
latentLATENT
directionCOMBOcomfy_to_pid2 options: comfy_to_pid, pid_to_comfy
scale_factorFLOAT0.3611-100–100
shift_factorFLOAT0.1159-100–100

Outputs (2)

NameTypeDescription
latentLATENT
infoSTRING