Nodes/ComfyUI-Apt_Preset/color_transferColor
ComfyUI Node

color_transferColor

Steal a reference image's palette without re-generating anything

By cardenluo·Created 2 years ago·Updated 4 days ago· 362
color_transferColor
  • ref_img
  • target_image
  • ref_mask
  • target_mask
  • image
◄method▾►
◄strength1.00►

What it's for

You have an image you like. You have another image with the light and palette you want, and no amount of prompt fiddling is going to get the first one to agree with the second. color_transferColor fixes that in one node: it moves your target image's colours onto the reference image's statistics. It's not a model, it doesn't sample anything, and it runs in milliseconds.

This is the underrated tool in the post-processing layer, because the thing it replaces is expensive and random. An inpainting patch that doesn't match its surroundings, an upscaled tile that's slightly warmer than its neighbours, a composited subject standing in a new background's light - all three are the same complaint, "the colours are off", and all three get re-generated by people who don't know a statistics transfer exists. A transfer is deterministic and instant; a re-gen is neither, and it changes the composition too.

How it works

The node is a thin wrapper around ComfyUI core's own Transfer Color node (comfy_extras/nodes_post_processing.py), which does the actual maths in LAB space. You pick one of three methods, increasingly aggressive:

  • reinhard_lab - the classic Reinhard mean/std transfer, per channel. Cheap, predictable. This is the one to start with.
  • mkl_lab - a full 3×3 linear transform. It also moves correlation between channels, so it handles a scene that's blue in the shadows and orange in the highlights instead of just shifting everything one way.
  • histogram - per-channel CDF matching through a 256-bin LUT, forcing your image's tonal distribution onto the reference's. Strongest, least subtle; for real grading rather than a nudge.

The pack's own twist is the masking. Core's node matches whole images. This one builds a pixel mask for each side: ref_mask decides which pixels of the reference define the palette, target_mask decides where the result is applied. So you can mask the sky in a reference, let only sky pixels set the colour target, and apply that to your subject alone. Fully transparent pixels are excluded from the statistics too, so an alpha-cut subject doesn't pollute its own reference with transparent black, and alpha is preserved on the output.

One detail worth knowing: the pack calls into core with source_stats fixed to uniform, meaning the statistics are pooled across every frame of the target batch before transforming. For a video or a batch that's exactly what you want - the frames stay consistent instead of each drifting toward the reference on its own.

The inputs and outputs that matter

Four required inputs, two optional, one output.

  • ref_img - the image whose look you want. This is the reference, not the victim.
  • target_image - the image that gets changed.
  • method - the three above. If you don't know, reinhard_lab.
  • strength - 0 to 10, default 1. At 1 you get the full transform; at 0 the node short-circuits and returns your target untouched; above 1 it deliberately overshoots past the reference. Overshoot is genuinely useful when the reference is subtle and you're matching across a heavier shift.
  • ref_mask and target_mask - optional MASK inputs. Leave them unwired and the whole image is used on both sides.
  • Output: image - a single IMAGE, same resolution as your target, alpha intact.

Masks get resized to the target's dimensions with bilinear interpolation and single-frame masks get expanded across the batch, which means you can feed a soft, feathered mask and get a soft blend rather than a hard edge. The mask value is used as a per-pixel blend weight on top of strength, so 50% grey half-matches.

Install

It ships in ComfyUI-Apt_Preset - one pack, 200-odd nodes, so you install it once and get all of them:

cd ComfyUI/custom_nodes
git clone https://github.com/cardenluo/ComfyUI-Apt_Preset
cd ComfyUI-Apt_Preset
python -m pip install -r requirements.txt   # use your ComfyUI's python

Then restart ComfyUI, or install via ComfyUI Manager by pack title. On Windows the author ships install-ComfyUI-Portable.bat and install-ComfyUI-aki.bat (the README still says "install.bat", which no longer exists). This node needs nothing but ComfyUI core - no model downloads.

Common issues

You wired it backwards. The two image inputs are the same type, so nothing will stop you, and putting the reference in target_image gives you the exact inverse of the effect you wanted with no error message. That's the number-one self-inflicted wound here. Wire the pretty one to ref_img.

Nothing changed. Either strength is 0 (early return - the node doesn't even compute), or one of your masks is empty/all-zero. The node bails out and hands your target back untouched when either side has no valid pixels left after masking.

Video and mixed batches. Statistics are pooled across the whole target batch, so a clip that legitimately changes colour mid-shot gets averaged into one palette. That's deliberate - it keeps frames consistent - but it's a real limit.

The whole pack is missing, not just this node. Apt_Preset's __init__.py imports every module up front with no per-module try/except, so one unmet dependency takes the entire node list down - the community error is a blank "IMPORT FAILED" line for the pack folder. If no Apt_Preset node appears at all, run the requirements install above and restart.

CategoryApt_Preset/image/color_adjust

Inputs (6)

NameTypeDefaultDescription
ref_imgIMAGE—
target_imageIMAGE—
methodCOMBO3 options: reinhard_lab, mkl_lab, histogram
strengthFLOAT1.000–10—
ref_maskoptMASK—
target_maskoptMASK—

Outputs (1)

NameTypeDescription
imageIMAGE—