Color Match
Make one image inherit another's palette, statistically
- image
- reference_image
- mask
- image
- mask
- color_match_info
The most underrated operation in all of post-processing: take your image and a reference, and move your image's colors toward the reference's statistics. That's color matching, and it's the honest fix for three jobs people keep solving by re-rolling generations - outpainted regions that don't match the original, upscaled tiles that don't match their neighbors, and composites that don't sit in the background's light. x1ColorMatch does it with a reference_image input and one knob. It's in MKRShift Nodes' Color/Finish branch.
The pack is young (no impressions yet, nothing on Reddit when I looked), so don't expect a community consensus on it - but the mechanism here is textbook and deterministic.
How it works
Reinhard-style statistics transfer, readable straight from the source. It computes the per-channel mean (and standard deviation) of your image and of the reference, then reshapes yours to match. The method setting picks the flavor:
mean_std(default) - matches mean and standard deviation per channel. This is the full palette transfer, the one you reach for when an inpainted patch just doesn't sit in the frame.mean_only- matches just the per-channel mean. Gentler; useful when you want the white balance aligned but don't want the reference's contrast characteristics shoved onto your image.
strength (0–1, default 0.85) blends the matched result back with the original, and preserve_luma rescales so the output keeps your image's luminance - the move when you want the palette but not the exposure. The reference is resized to your image's dimensions internally, so you can feed it any resolution. An optional mask limits the match to a region, which is how you fix a bad patch without touching the rest of the frame.
Outputs: image, mask (the match matte), color_match_info (method, strength, reference batch count, mask coverage).
Inputs that matter
reference_image- the required second input; its palette is what your image inheritsmethod-mean_stdfor full transfer,mean_onlyfor white-balance-style alignmentstrength- 0.85 default is strong; back off to ~0.5 when the reference is a vibe, not a sourcepreserve_luma- on when you want palette only
Installing
ComfyUI Manager → search MKRShift Nodes, or:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
Restart ComfyUI. No models, no new dependencies.
Where people get burned
- A bad reference is a bad match. Match to a reference whose lighting is wildly different and you'll import its cast along with its palette. Pick references that share your scene's light.
- Full-frame
mean_stdon a mostly-sky reference can flatten your subject's color range. Mask the match, or drop tomean_only. - The
maskoutput is the match matte, not your input mask. Pack-wide convention. - Corrupted
settings_jsonresets to defaults silently - if the match stops landing, check the JSON.
It's the tool for "the colors are off" - a deterministic, instant answer to what a re-gen would do randomly and slowly. The KB's post-processing doc calls this exact operation the underrated one; this node is the fastest way to try it in-graph.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| reference_image | IMAGE | — | |
| settings_json | STRING | {"method":"mean_std","strength":0.85,"preserve_luma":false,"mask_feather":12.0,"invert_mask":false} | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| color_match_info | STRING | — |