Nodes/Comfy Latent Tools/Latent Normalized Lanczos Resize(LNLR)
ComfyUI Node

Latent Normalized Lanczos Resize(LNLR)

A latent upscale that doesn't blur — decode, Lanczos, re-encode, match moments

By JTriggerFish·Created 2 years ago·Updated about a year ago· 4
Latent Normalized Lanczos Resize(LNLR)
  • latent
  • vae
  • LATENT
size_multiplier2.0
soft_clamp_outlierstrue
outlier_quantile0.01
outlier_clamp_slope0.1
add_latent_noisefalse
latent_noise_std1.00
latent_noise_scale0.10
add_latent_upscale_with_weight0.00
noise_seed0

Here's the classic hi-res fix problem. You upscale a latent, run a second KSampler pass at low denoise, and the image comes out soft. If you used the plain latent upscale nodes, that's why - a nearest-neighbor upscale in latent space is a blur factory, and "latent upscale blurs my image" is a recurring complaint in r/comfyui for a reason.

LatentNormalizedLanczosResize (LNLR) is the fix that people hand-roll anyway, in one node: decode to pixels, upscale with a real Lanczos interpolator in image space, re-encode, and - the part most hand-rolled versions skip - force the new latent's statistics to match the original. It lives in the image/upscaling category and outputs a LATENT, so it plugs in exactly where "Upscale Latent" used to sit, ahead of a second KSampler.

How it works

The internal order is spelled out in the source and it's worth knowing because it tells you why it behaves:

  1. Soft outlier clamp (on by default) - uses a huberize_quantile step to compress extreme latent values instead of hard-clipping them, so decode doesn't amplify noise spikes.
  2. Decode - latent to image through your VAE.
  3. Lanczos upscale - image upscaled by size_multiplier.
  4. Re-encode - back to latent space.
  5. Optional blend - if add_latent_upscale_with_weight is above 0, the re-encoded latent is blended toward a direct nearest-exact latent upscale of the original.
  6. Moment matching - the core trick: per-channel mean and variance of the upscaled latent are matched to the original latent. This is what keeps it from looking washed out or contrast-shifted the way a naive decode→encode round trip does.
  7. Optional correlated Gaussian noise - smoothed noise added back, for variation.

Inputs that matter

  • latent and vae - your latents and the VAE that decoded them.
  • size_multiplier (default 2, range 0.1–4) - the resize factor. 2x is the sweet spot; 4x means a much bigger second pass and more VRAM.
  • soft_clamp_outliers (default on) - leave it on; outlier_quantile (0.01) and outlier_clamp_slope (0.1) tune how aggressive the clamp is.
  • add_latent_upscale_with_weight (default 0) - 0–1, blend toward a plain nearest latent upscale. If you want a bit of that latent-space character back, nudge it up.
  • add_latent_noise (default off) with latent_noise_std (1.0), latent_noise_scale (0.1) and noise_seed - correlated noise to inject detail variation when the second pass is about adding texture, not just resolution.

The output is a single LATENT. Wire it into a second KSampler at low denoise (0.3–0.5 is the classic hi-res fix range).

Where it sits in the upscaling ladder

Be clear about what this isn't. LNLR is the "more pixels" rung, not the "more detail" rung - Lanczos adds no content and can't hallucinate, which is a feature when you just want a sharp, faithful base for re-diffusion. If you need genuine detail restoration, you're in SeedVR2/SUPIR territory, which is a different job. This is the cheap, predictable, milliseconds-fast option in the middle of a hi-res fix workflow.

Install and gotchas

ComfyUI Manager, search Comfy Latent Tools, install, restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/JTriggerFish/ComfyLatentTools

Then restart. No model downloads; dependencies are just torch, torchvision, pillow and numpy.

Three things to know before you trust it in a production workflow. It costs a VAE decode plus an encode every run, so it's slower than a pure latent upscale - that's the price of the sharper base. The pack is openly experimental (README: "MANY MISSING NODES HERE - WILL BE UPDATED"), so pin the version you're happy with. And the noise is off by default for a reason: it's the knob that introduces variation, but crank latent_noise_scale too high and the second pass starts inventing artifacts. Start with it off, add it only if your refinement pass comes out too sterile.

Categoryimage/upscaling

Inputs (11)

NameTypeDefaultDescription
latentLATENT
vaeVAE
size_multiplierFLOAT2.00.1–4
soft_clamp_outliersBOOLEANtrue
outlier_quantileFLOAT0.010–1
outlier_clamp_slopeFLOAT0.10–1
add_latent_noiseBOOLEANfalse
latent_noise_stdFLOAT1.000–10
latent_noise_scaleFLOAT0.100.01–10
add_latent_upscale_with_weightFLOAT0.000–1
noise_seedINT00–18446744073709550000

Outputs (1)

NameTypeDescription
LATENTLATENT