Color Match FunCode
Instant palette transplants — no re-rolls needed
- image_ref
- image_target
- image
When the colors are "off" in a generated image, the default move is to re-roll the generation and hope. Color Match FunCode is the cheap deterministic alternative: it takes a target image and a reference, and moves the target's palette toward the reference's - in a few hundred milliseconds, every time. This is the same family of statistics-based color transfer that underpins most color-grading utilities, wrapped in a ComfyUI node with six methods to pick from.
It's the node to reach for when an outpainted region doesn't match the original, when a composited subject sits in a scene with the wrong light, or when an upscaled tile disagrees with its neighbours. Those are exactly the jobs the post-processing layer's "cheap primitive before expensive generative fix" rule is about: a color match is instant and deterministic; a re-gen is neither.
How it works
Under the hood it uses the color-matcher library (the same one cited in the node's own description) - the classic ColorMatcher().transfer(src, ref, method) call, which aligns the target's color statistics to the reference's using one of several algorithms:
- mkl (default) - Monge–Kantorovich Linear, a robust full-color transfer that's a solid general-purpose default.
- hm - histogram matching, per-channel.
- reinhard - the original Reinhard mean/std transfer; fast and good enough for many jobs.
- mvgd - multivariate Gaussian distribution matching.
- hm-mvgd-hm, hm-mkl-hm - histogram-prefixed hybrids that tend to look more natural.
There's no neural network and no model file - this is pure numpy math on the pixels. The strength slider blends between the original and the full transfer (output = original + strength × (result − original)), so 0 is untouched, 1 is the full match, and anything above 1 overshoots deliberately.
Inputs and output
The three required inputs are the whole story:
- image_ref - the image whose color feel you want.
- image_target - the image being recolored.
- method - one of the six above;
mklis the sane default until you have a reason to switch.
Optionals: strength (default 1.0, range 0–10) and multithread (default on, which parallelizes the work across a batch on CPU - a real speedup if you're matching a whole video frame batch).
Output is a single image, ready for a preview node or straight back into your pipeline.
Installing
Same pack, with one extra step: this is the only node in ComfyUI_FunCode that needs the pack's pip dependency, and the node refuses to run without it:
cd ComfyUI/custom_nodes
git clone https://github.com/kaiery/ComfyUI_FunCode
pip install -r requirements.txt # installs color-matcher
Then restart ComfyUI. No model files, nothing else to fetch.
Common issues
- "Can't import color-matcher, please install it first" - the exact error you get if you skipped the pip step. Run
pip install color-matcherand restart. - Batch size mismatch - the reference batch must be either 1 or the same size as the target batch. Feed a single reference and a batch of frames and it applies that one reference to every frame; feed matched pairs and it does per-frame transfer.
- Colors look washed or blown out - strength above 1 overshoots by design. Drop it back toward 1 (or below) and try
hm-mkl-hmifmklfeels too aggressive.
One honest note: the pack is small and fresh, so don't expect a big community consensus on which method "wins." For most composites, default mkl at strength 1.0 looks right, and you're done in the time it took to read this paragraph.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image_ref | IMAGE | — | |
| image_target | IMAGE | — | |
| method | COMBO | mkl | 6 options: mkl, hm, reinhard, mvgd, hm-mvgd-hm, hm-mkl-hm |
| strengthopt | FLOAT | 1.000–10 | — |
| multithreadopt | BOOLEAN | true | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |