Nodes/MKRShift_Nodes/Color Match
ComfyUI Node

Color Match

Make one image inherit another's palette, statistically

By criskb·Created 7 months ago·Updated 5 months ago· 0
Color Match
  • image
  • reference_image
  • mask
  • image
  • mask
  • color_match_info
settings_json{"method":"mean_std","strength":0.85,"preserve_luma":false,"mask_feather":12.0,"invert_mask":false}

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 inherits
  • method - mean_std for full transfer, mean_only for white-balance-style alignment
  • strength - 0.85 default is strong; back off to ~0.5 when the reference is a vibe, not a source
  • preserve_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_std on a mostly-sky reference can flatten your subject's color range. Mask the match, or drop to mean_only.
  • The mask output is the match matte, not your input mask. Pack-wide convention.
  • Corrupted settings_json resets 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.

CategoryMKRShift Nodes/Color/Finish

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
reference_imageIMAGE
settings_jsonSTRING{"method":"mean_std","strength":0.85,"preserve_luma":false,"mask_feather":12.0,"invert_mask":false}
maskoptMASK

Outputs (3)

NameTypeDescription
imageIMAGE
maskMASK
color_match_infoSTRING