Nodes/WAS Node Suite v3/WAS Adaptive Difference Latent Upscale (Damped)
ComfyUI Node Runs on cloud

WAS Adaptive Difference Latent Upscale (Damped)

A latent upscale that dodges ringing at edges

By WASasquatch·Created 3 years ago·Updated 3 days ago· 1,832
WAS Adaptive Difference Latent Upscale (Damped)
  • latent
  • latent
  • mask
  • mask_preview
scale2.00
smooth_modebilinear
diff_blur_sigma0.60
threshold0.120
softness0.050
weight_power1.00
weight_blur_sigma0.00
temporal_ema0.00
enable_directional_dampingtrue
damping_strength0.35
damping_gate_modeweight_sqrt
damping_grad_blur_sigma0.00
damping_threshold0.250
damping_softness0.080
damping_power1.00
damping_mask_blur_sigma0.60
damping_highpass_sigma1.00
damping_temporal_ema0.25
preview_modeboth
output_mask_pixel_scale8

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 what mask_preview actually 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.

CategoryWAS Suite/Latent/Transform

Inputs (21)

NameTypeDefaultDescription
latentLATENTThe latent to enlarge. A video latent with a time axis is handled frame by frame.
scaleFLOAT2.001–8How much larger the result is. 2.0 doubles both sides, 1.5 adds half again, 1.0 leaves the size alone and only applies the damping. Sizes are rounded to whole latent blocks.
smooth_modeCOMBObilinearHow the smooth half of the blend is enlarged. `bilinear` is the safe default; `bicubic` is sharper and can overshoot slightly at a hard edge; `area` averages the source region and is the softest of the three.
diff_blur_sigmaFLOAT0.600–8How far the disagreement between the two enlargements is spread before it decides anything, in latent blocks. A little blur keeps the blend from switching on and off block by block; 0.0 uses the raw per-block difference and gives the busiest map.
thresholdFLOAT0.1200–1How much disagreement counts as detail. Below this the blocky enlargement is kept, above it the smooth one takes over. Lower values smooth more of the picture; 0.12 leaves flat areas crisp and treats edges.
softnessFLOAT0.0500.0005–1How gradual the changeover at the threshold is. Small values such as 0.005 give a hard switch that can be seen as a rim; 0.05 fades between the two enlargements over a comfortable range.
weight_powerFLOAT1.000.1–6Bends the blend map after it is built. Above 1.0 pulls it towards the blocky enlargement everywhere but the strongest edges; below 1.0 spreads the smooth enlargement into weaker detail. 1.0 leaves the map as measured.
weight_blur_sigmaFLOAT0.000–8Softens the finished blend map, in latent blocks. Raise it when the treated areas have visible outlines of their own; 0.0 leaves the map alone.
temporal_emaFLOAT0.000–0.99How much each frame of a video latent carries over from the frames before it, which stops the blend map flickering. 0.0 treats every frame on its own; 0.5 is a light smoothing; 0.9 is heavy and can smear the map behind fast motion. Ignored on a single image.
enable_directional_dampingBOOLEANtrueWhether the second pass runs, which takes fine detail back out along strong boundaries. It is what removes the halo that an upscale leaves around hard edges. Turn it off to see the blend on its own, or when the source is already soft.
damping_strengthFLOAT0.350–1How much fine detail is removed where the damping mask is fully on. 0.0 removes none and turns the pass off; 0.35 takes the edge off a halo; 1.0 flattens the detail there completely.
damping_gate_modeCOMBOweight_sqrtWhere the damping is allowed to act. `none` lets it act on every boundary it finds. `weight` confines it to the areas the blend already treated. `weight_sqrt` is in between, allowing some damping in areas the blend touched only lightly.
damping_grad_blur_sigmaFLOAT0.000–8Blur applied before boundaries are looked for, in latent blocks. Raise it so that texture is not mistaken for an edge; 0.0 finds the finest boundaries.
damping_thresholdFLOAT0.2500–1How strong a boundary has to be to be damped, measured against the strongest one in the picture. 0.25 catches the clear outlines; lower values reach into texture as well.
damping_softnessFLOAT0.0800.0005–1How gradually the damping fades in around that threshold. Small values give a hard-edged mask; 0.08 fades over a comfortable range.
damping_powerFLOAT1.000.1–6Bends the damping mask. Above 1.0 confines the damping to the very strongest boundaries; below 1.0 spreads it over more of the picture. 1.0 leaves the mask as measured.
damping_mask_blur_sigmaFLOAT0.600–8Softens the damping mask before it is used, in latent blocks. A little blur keeps the damped strip from having a visible border of its own; 0.0 uses the mask as found.
damping_highpass_sigmaFLOAT1.000–8Which detail counts as fine enough to be removed, in latent blocks. 1.0 takes out ringing while leaving the shapes; larger values reach into broader structure and start to blur. 0.0 removes the whole signal under the mask instead.
damping_temporal_emaFLOAT0.250–0.99How much of the damping mask each frame of a video latent carries over from the frames before it, so damped areas do not shimmer. 0.0 treats every frame on its own. Ignored on a single image.
preview_modeCOMBObothWhich map leaves the node. `weight` shows where the smooth enlargement was used, `damp` shows where fine detail was removed, `both` puts the two side by side in the preview and sends the damping map to the mask output.
output_mask_pixel_scaleINT81–16How many preview pixels each latent block becomes. 8 matches the size the latent decodes to on most VAEs, so the preview lines up with the finished picture; 1 gives the small raw map. This affects the preview image only, never the mask output.

Outputs (3)

NameTypeDescription
latentLATENTThe enlarged latent, ready for a sampler or a decode.
maskMASKThe map the node worked from, at latent resolution: the damping map on `damp` and `both`, the blend map on `weight`. Useful for driving another node from the same areas this one treated.
mask_previewIMAGEThe same map as a viewable image, enlarged by output_mask_pixel_scale. On `both` the blend map is on the left and the damping map on the right.