Color Match (Badman)
Learn a color-drift fix from one pair, apply it to everything
- image
- source_ref
- target_ref
- source_mask
- target_mask
- image_mask
- image
- mask
- preset_path
The problem this solves is a familiar one if you've done any batch generation or img2img chains: color drifts. Run the same character through a few generations, an upscale, an inpaint pass, or a style transfer, and the palette creeps - skin goes a bit too orange, whites go a bit too warm, and by the tenth image in a batch it's visibly off from the first. Color Match's approach is to learn the correction once, from a single before/after pair, and then reuse it.
How it actually works
You give it a source_ref (the drifted version) and a target_ref (the clean version you want to match) as an optional reference pair. From that pair, the node learns a color transform and applies it to your main image input. Two methods are on offer: reinhard, which matches LAB mean and standard deviation - a gentle, statistically safe correction that tends to generalize well across images with different palettes; and hist, which does full LAB per-channel histogram matching - a much stronger, more literal correction, but one that's tuned to the specific reference pair's palette and can look wrong applied to an image with a genuinely different color range. reinhard is the safer default; reach for hist when drift is bad enough that the gentler option isn't cutting it.
The feature that separates this from a one-off color-match node: you can save the learned transform as a named preset (save_as) and reload it later via use_preset + preset_name, instead of re-supplying the reference pair every time. Build the correction once against your worst-drifted example, save it, and apply it across a whole batch or an entire project without wiring reference images into every single run. It also reportedly runs a live ~180ms preview when you drag strength or swap presets, without re-queueing the workflow - a genuinely nice bit of interactivity for a node this utilitarian.
The inputs that matter
image- what gets corrected.use_preset(boolean) - flip on to apply a saved preset instead of a live reference pair.preset_name- which saved preset to use, whenuse_presetis on.method(reinharddefault, orhist) - see above.strength(0–1, default1) - how much of the correction to apply; dial back if a full-strength match looks overcooked.save_as/overwrite- name and save the transform you just learned as a reusable preset.
Optional: source_ref / target_ref (the reference pair, when not using a preset) and source_mask / target_mask / image_mask (MASK) to restrict where the learning and application happen.
Three outputs: the corrected image, a mask, and preset_path (STRING) - the location of the preset you just saved, if you saved one.
Installing it
ComfyUI Manager: search ComfyUI-BadmanNodes, install, restart. Manual: cd ComfyUI/custom_nodes && git clone https://github.com/MariusKM/ComfyUI-BadmanNodes. No extra dependencies noted - presets get written to disk somewhere under the node's own storage, but that's file I/O, not a model download.
Where people get burned
Method mismatch is the big one, and it matters beyond a single run: if you're building toward this pack's Color Match Combine Presets node to average several saved presets together, they all need to share the same method - mixing a reinhard-learned preset with a hist-learned one won't combine sensibly. Decide on a method before you build out a preset library, not after. Second, a preset learned from one reference pair is only as general as that pair was - a transform learned to fix orange-tinted skin on a portrait can do something bizarre to a landscape shot with no skin tones in it at all, so don't assume a preset generalizes further than the kind of image it was trained on. And if strength at 1 looks like it's overcorrecting, that's usually a sign the reference pair itself had more drift in it than your actual image does - turn strength down before reaching for a different method.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| use_preset | BOOLEAN | false | — |
| preset_name | COMBO | 1 options: anti-terracotta | |
| method | COMBO | reinhard | 2 options: reinhard, hist |
| strength | FLOAT | 1.000–1 | — |
| save_as | STRING | — | |
| overwrite | BOOLEAN | false | — |
| source_refopt | IMAGE | — | |
| target_refopt | IMAGE | — | |
| source_maskopt | MASK | — | |
| target_maskopt | MASK | — | |
| image_maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| preset_path | STRING | — |