ComfyUI Node

GradientBlur

Gradient blur in one node — no mask-painting required

By badxprogramm·Created about a year ago·Updated about a year ago· 1
GradientBlur
  • image
  • image
  • gradient_mask
intensity10.00
direction
auto_centertrue
center_x0.50
center_y0.50
sharp_edgetrue
bias0.00

You know that soft-focus portrait shot where the background melts away but the subject stays tack sharp? Normally you'd paint a mask by hand or wrestle with a blur node plus a compositing chain to fake it. GradientBlur is the shortcut: one node, one image in, and it fades a Gaussian blur across the frame along a direction you pick. No mask painting, no blending math, no second model. It's the kind of tiny utility that quietly lives in your graph once you've used it twice - great for a depth-of-field feel on a landscape, or for blurring out the top or bottom of an image before you feed it somewhere else.

It's a single-file pack from badxprogramm (MIT licensed, no models, no extra dependencies), and it does exactly one thing. That's the whole pitch.

How it works

Peek at nodes.py and the mechanism is refreshingly honest. The node builds a gradient mask as a 0-to-1 ramp across the image - a linear ramp down the frame for the axis directions (top_to_bottom, left_to_right, and their reverses), or a radial falloff from a center point for custom. Then it blurs the whole image and cross-fades between the original and the blurred copy using that mask: result = original * (1 - mask) + blurred * mask. Where the mask is 1, you get full blur; where it's 0, the original is untouched. That's the entire trick, and it's why the transition is always smooth and why the node works on RGB, RGBA, and single-channel images alike.

The blur itself is a Gaussian with sigma = intensity and a kernel of intensity * 2 + 1 pixels, run with ComfyUI's built-in blur helper. Two details worth knowing: at intensity = 0 the node short-circuits and returns the input untouched (nice and cheap, that's the "optimization" the README brags about), and the whole batch shares one gradient, so the same fade applies to every frame in a batch.

The inputs that actually matter

  • intensity (0–100, default 10) - the only knob you'll touch most sessions. 1–20 is the sane range; past 40 you're deep into smudge territory with sigma to match.
  • direction - the five choices are custom, top_to_bottom, bottom_to_top, left_to_right, right_to_left. Pick an axis and you're done.
  • auto_center (default on) - trap alert: when custom is selected and auto_center is on, your center_x/center_y values are ignored and forced to the middle. Flip it off if you actually want an off-center fade.
  • bias (−1 to 1, default 0) - shifts the whole mask toward blur or no-blur. Positive values make more of the frame blurred; negative keeps more of it sharp. It's the closest thing to a "how much area gets blurred" slider.
  • sharp_edge (default on) - when on, axis directions get a clean linear ramp. When off, every direction silently becomes a radial gradient from the center, so don't expect linear behavior with it disabled.

Wiring the outputs

Two outputs, both IMAGE. image is the blurred composite - feed it straight to a Save Image or into whatever comes next. gradient_mask is a grayscale preview of the mask that was applied, which is great for eyeballing where the fade actually lands. One gotcha: it's an IMAGE, not a MASK tensor, so you can't plug it directly into a mask input like an inpainting node - run it through ComfyUI's ImageToMask first if that's the plan.

Install

ComfyUI Manager - search "GradientBlur" (the pack title is "GradientBlurNode for ComfyUI") and install. Or do it by hand:

cd ComfyUI/custom_nodes
git clone https://github.com/badxprogramm/ComfyUI-GradientBlur

Then restart ComfyUI. No requirements.txt, no model downloads, nothing to configure - which is more than most custom nodes can say.

Where it can bite you

The honest warning: this node calls gaussian_blur, which it pulls in via from comfy_extras.nodes_upscale_model import * - and as of current ComfyUI master that module doesn't define a gaussian_blur anymore (the shipped helper is gaussian_blur_2d in nodes_sag.py). In practice that means on a modern ComfyUI the node loads fine but throws NameError the moment intensity is above 0. It's a two-line fix - swap in gaussian_blur_2d or any of the blur nodes already in your graph - but don't assume "install and it just works" here. The zero-dependency, one-function design is great right up until the upstream function it leans on moves. If the node errors on you, that's the first thing to check.

Categoryimage/blur

Inputs (8)

NameTypeDefaultDescription
imageIMAGE
intensityFLOAT10.000–100
directionCOMBO5 options: custom, top_to_bottom, bottom_to_top, left_to_right, right_to_left
auto_centerBOOLEANtrue
center_xFLOAT0.500–1
center_yFLOAT0.500–1
sharp_edgeBOOLEANtrue
biasFLOAT0.00-1–1

Outputs (2)

NameTypeDescription
imageIMAGE
gradient_maskIMAGE