πΎ Noise Grain Pro
Real film grain without the film β grain size, sharpness, and six blend modes
- image
- mask
- image
The photorealism tell isn't sharpness, it's the opposite: AI images are too clean. Real photos have grain - a little texture that stops flat gradients from banding and keeps skin from looking like polished plastic. πΎ Noise Grain Pro is a film-grain generator that adds that texture properly: independent grain size, sharpness, mono/color control, six industry blend modes, a seed for reproducibility, and mask support so you can grain a subject but not its background. It's the "make it feel like a photograph" pass.
How it works (the interesting bit)
The mechanism is smarter than just adding random noise to every pixel. Grain size is faked by generating the noise at a reduced resolution, then upscaling it to the image - the bigger the size value (0.5 to 10), the lower the noise resolution, so grain particles get visibly chunkier without looking like digital static. sharpness (0β1) works inversely: lower sharpness blurs the noise more, giving soft, diffused grain; higher keeps it crisp. In monochromatic mode it's single-channel noise broadcast to RGB; turn it off and you get per-channel color noise with saturation controlling the color intensity.
Then the grain is normalized and blended into the image using one of six modes - overlay, soft_light, hard_light, linear_light, multiply, screen. The README is explicit that soft light uses the correct W3C/Photoshop formula, which is the kind of detail that separates a usable grain node from a toy. amount (0β1) mixes the blended result with the original, and an optional mask limits where grain lands.
Inputs and outputs worth knowing
Required: image and blend_mode. Optional: amount, size, sharpness, saturation, monochromatic, seed, mask. The one beginners trip on is seed - it defaults to 0, and since grain is random, every run looks different unless you fix a seed. If you want reproducible grain across runs, set it once and keep it. Output is a single image (the node is marked as an output node, so it renders in-graph as your final/preview step).
When to use it (and when not)
Classic move: after upscaling, grain gets scaled away, so adding grain after your upscale pass is the standard order. It also quietly fixes banding in skies and smooth gradients - a touch of grain plus the right blend mode (soft light is gentle, overlay is a bit stronger, linear light is aggressive) hides posterization. That's the overhyped-thing caveat, though: a light hand. Grain is a seasoning, not a filter; crank amount to 1 with linear light and you've just made your clean render look like a noisy scan. Start at 0.2β0.4, size 1β2, and judge on the final image, not the zoomed preview.
Installing it
Ships in the MachinePainting Nodes pack. ComfyUI Manager β search "MachinePaintingNodes", or:
cd ComfyUI/custom_nodes
git clone https://github.com/machinepainting/ComfyUI-MachinePaintingNodes.git
Restart ComfyUI. The pack's requirements are opencv-python-headless, numpy<3, rembg; grain itself uses numpy + OpenCV, so expect it to run on CPU fine.
Gotchas
- Seed 0 default means non-reproducible grain. If you're comparing two renders, lock the seed or the grain difference will fool you into thinking a parameter changed something.
- Mask input shapes are resized to match, which is polite, but a low-res mask upscaled to 4K gives soft boundaries - upscale the mask if you want a crisp grain cutoff.
- Big
sizevalues on huge images make the upscale interpolation obvious if you look close; 10 is basically "add film texture," not "add grain."
It's the one filter in this pack I'd call genuinely pleasant to use - and with the correct soft-light math, it doesn't make your image look worse while pretending to be filmic.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | β | |
| blend_mode | COMBO | overlay | 6 options: overlay, soft_light, hard_light, linear_light, multiply, screen |
| amountopt | FLOAT | 0.500β1 | β |
| sizeopt | FLOAT | 1.00.5β10 | β |
| sharpnessopt | FLOAT | 0.500β1 | β |
| saturationopt | FLOAT | 0.000β1 | β |
| monochromaticopt | BOOLEAN | true | β |
| seedopt | INT | 00β4294967295 | β |
| maskopt | MASK | β |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | β |