Nodes/ComfyUI-FrameUtilitys/Wavelet Color Fix
ComfyUI Node

Wavelet Color Fix

Steal the color grade from one shot and keep your detail

By lum3on·Created about a year ago·Updated 2 months ago· 16
Wavelet Color Fix
  • target_image
  • source_image
  • image
align_methodwavelet

Color drift is the silent killer of otherwise-good image work. You upscale a frame, re-render a pass, or push something through a second model, and suddenly the colors aren't quite the reference anymore. WaveletColorFix exists to pull that back: it takes the color from one image and lays it onto another - while leaving the target's fine detail alone. If you've ever wished you could "make this look like that" without a LUT and without flattening the image, this is that node.

How it works

It's a color-transfer node with two different algorithms under one align_method dropdown, and the choice genuinely changes what happens:

  • adain (Adaptive Instance Normalization) - matches the global color statistics: it normalizes the target's per-channel mean and standard deviation to match the source's. Simple, global, one shot. Your target takes on the source's overall brightness, contrast, and tint.
  • wavelet (default) - smarter about detail. It decomposes each frame into low-frequency (color/blur) and high-frequency (detail/edges) components using a 5-level pyramid of blurring convolutions, keeps the target's high-frequency detail, and swaps in the source's low-frequency color. Result: the target keeps its sharpness while inheriting the source's palette.

The wavelet path is the one you'll actually want for fixing upscaled images, because a plain color match tends to smear detail - the whole point of the split is that it doesn't. If you want a flat global re-grade instead, AdaIN is the blunt instrument for the job.

It processes frame-by-frame with a progress bar, and if you feed it a video where source and target have different frame counts, it loops the shorter one and logs a warning rather than failing. Inputs are target_image (the one whose detail you keep), source_image (the one lending its colors), and align_method. Output is image, ready for SaveImage or the next node. It needs RGB or RGBA input; if your target is RGBA, the alpha channel passes through intact.

Where this kind of node shows up

You'll recognize the lineage if you've done upscaling workflows: this is the same color-fix trick that StableSR and its ports bake in, where the upscaled output gets color-matched back to the original because pure upscalers quietly shift color. Here it's exposed as a standalone node, so you can drop it in anywhere the color drifted - a rediffused frame, a frame from a different model's pass, a video clip that needs to match a reference grade. It's the kind of small utility that quietly saves you fifteen minutes of curve fiddling in an editor.

Installing

Manager: search "ComfyUI-FrameUtilitys". Or:

cd ComfyUI/custom_nodes
git clone https://github.com/lum3on/ComfyUI-FrameUtilitys

Restart. Zero extra dependencies - it's pure PyTorch plus ComfyUI's own comfy.utils progress bar, so nothing to download.

Troubleshooting

  • "Expected a 4D tensor" / "must be IMAGE tensors" - both inputs need to be IMAGE type in [B, H, W, C] format, straight from LoadImage or a video loader.
  • Colors look flat or washed - you're probably on adain, which is the global-statistics path. Switch to wavelet to keep detail and get a subtler transfer.
  • Frame count mismatch warning - expected if your clips aren't the same length; the source just loops. Check the console if the result looks wrong.
Categoryimage/video

Inputs (3)

NameTypeDefaultDescription
target_imageIMAGEImage or frame sequence whose detail should be preserved
source_imageIMAGEImage or frame sequence providing the color statistics
align_methodCOMBOwaveletAdaIN matches global color statistics; wavelet transfers low-frequency color

Outputs (1)

NameTypeDescription
imageIMAGE