WAS Adaptive Difference Latent Upscale (Damped)
A latent upscale that dodges ringing at edges
- latent
- latent
- mask
- mask_preview
Naive latent upscaling - the plain nearest/bilinear resize most people reach for before a second KSampler pass - tends to ring and halo at hard edges, exactly where you'd most want the upscale to look clean. This node is built specifically to avoid that: it computes where the strong edges are, backs the upscale enhancement off around them, and leaves you a mask so you can actually see where it's protecting detail versus pushing it.
How it works
The base of it is a standard interpolated upscale at scale, using smooth_mode (bilinear, bicubic, or area). On top of that sits an "adaptive difference" system: the node measures how much the upscale changes the image locally, blurs that difference signal (diff_blur_sigma), and gates how strongly the difference gets applied using threshold/softness/weight_power - this is the general enhancement-strength control, before edges are even considered.
The edge protection specifically lives in the enable_directional_damping block. When it's on (default), the node builds a second, edge/energy-based mask via damping_gate_mode, damping_threshold, damping_softness, and damping_power, then uses damping_strength to scale down enhancement wherever that mask says "there's a strong edge here." damping_grad_blur_sigma and damping_mask_blur_sigma smooth that gradient/mask before it's applied, and damping_highpass_sigma isolates the high-frequency edge signal it's reacting to. For video latents, temporal_ema and damping_temporal_ema exponentially smooth both signals across frames, so the damping doesn't flicker frame to frame the way a per-frame-only calculation would.
If this sounds like a lot to internalize before you've upscaled anything - it is. Start with just scale and smooth_mode, leave everything else at default, and only reach for the damping controls once you can see a specific artifact you're trying to fix.
The inputs and outputs that matter
latent(LATENT) - what you're upscaling.scale(default 2, range 1–8) - the upscale factor. General latent-upscale convention favors modest factors (roughly 1.5–2x) per pass rather than pushing one huge jump - you can always chain a second pass.smooth_mode- bilinear/bicubic/area, the base interpolation before any adaptive/damping logic runs.damping_strength(default 0.35) - the single most important damping knob once you've decided edge protection needs adjusting. Higher backs off enhancement near edges more aggressively.preview_mode(weight / damp / both) - controls whatmask_previewactually shows you.
Three outputs: latent (the upscaled result, feed straight into your second-pass KSampler), mask (the computed weighting/damping mask as a MASK), and mask_preview (an IMAGE visualization of that mask, so you can actually see what the node did rather than guessing from the final result).
How to install it
Via ComfyUI Manager: search "WAS_Extras", install, restart. Manually:
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/WAS_Extras
Restart ComfyUI. No extra dependencies for this node.
Common issues & troubleshooting
Upscaled result looks flat or mushy, like detail got smoothed away. Damping is likely too aggressive for your image - lower damping_strength, or check mask_preview (set preview_mode to damp) to confirm the node thinks more of the image is "edge" than you'd expect.
Still seeing ringing or halos at edges despite damping being enabled. Check enable_directional_damping is actually on, then try lowering damping_threshold so more of the image counts as "edge enough" to protect, or raise damping_strength itself.
Video latents flicker between frames. That's what temporal_ema and damping_temporal_ema are for - both default to smoothing values above zero already (0 and 0.25 respectively), but if you're still seeing frame-to-frame instability, raise damping_temporal_ema further before touching anything else.
Too many parameters, not sure which one is causing a given artifact. Use mask_preview as your diagnostic first. preview_mode: both shows you the general enhancement weighting and the edge-damping mask together - it's faster to look at what the node computed than to guess from the final upscaled latent alone.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| latent | LATENT | — | |
| scale | FLOAT | 2.001–8 | — |
| smooth_mode | COMBO | bilinear | 3 options: bilinear, bicubic, area |
| diff_blur_sigma | FLOAT | 0.600–8 | — |
| threshold | FLOAT | 0.1200–1 | — |
| softness | FLOAT | 0.0500.0005–1 | — |
| weight_power | FLOAT | 1.000.1–6 | — |
| weight_blur_sigma | FLOAT | 0.000–8 | — |
| temporal_ema | FLOAT | 0.000–0.99 | — |
| enable_directional_damping | BOOLEAN | true | — |
| damping_strength | FLOAT | 0.350–1 | — |
| damping_gate_mode | COMBO | weight_sqrt | 3 options: none, weight, weight_sqrt |
| damping_grad_blur_sigma | FLOAT | 0.000–8 | — |
| damping_threshold | FLOAT | 0.2500–1 | — |
| damping_softness | FLOAT | 0.0800.0005–1 | — |
| damping_power | FLOAT | 1.000.1–6 | — |
| damping_mask_blur_sigma | FLOAT | 0.600–8 | — |
| damping_highpass_sigma | FLOAT | 1.000–8 | — |
| damping_temporal_ema | FLOAT | 0.250–0.99 | — |
| preview_mode | COMBO | both | 3 options: weight, damp, both |
| output_mask_pixel_scale | INT | 81–16 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| latent | LATENT | — |
| mask | MASK | — |
| mask_preview | IMAGE | — |