Nodes/ComfyUI-I2I-slim/Color Transfer
ComfyUI Node

Color Transfer

Give one image another image's palette, without wrecking the lighting

By GeraldWie·Created about a year ago·Updated about a year ago· 0
Color Transfer
  • source_image
  • target_image
  • mask
  • image
no_of_colors6
blur_radius2
blur_amount2
strength1.0
gamma1.0
contrast1.0
brightness1.0

"Surely there's a node for this." That's what you think the first time you have a render that's come out too cyan and a warm reference photo you'd love it to match. There is a node - this one - and it's smarter than the plain mean-and-standard-deviation color match you'll find scattered through other packs.

Color Transfer takes a source_image and a target_image, and makes the target wear the source's palette. Same composition, same lighting, different colors. Reach for it when you want a batch of renders to share one mood, when a prop texture has to blend into a scene it wasn't made for, or when you have a hero reference and want a generation to stop fighting it.

How it works

The mechanism is genuinely palette-based, not a global tint. It pulls the no_of_colors dominant colors out of the source (default 6), segments the target into color regions, pairs source and target palette colors by luminance, and swaps each region's color in. Then the strength dial decides how much of the target's original luminance survives the swap - that's the trick that keeps the result from going flat and plastic. A final gamma / contrast / brightness pass runs on top, and blur_radius / blur_amount control how the recolored regions blend at their edges.

There's an optional mask input, and it's worth knowing about: pass a MASK and the palette is only sampled from that part of the source. Want the target to take its greens from the grass and ignore the sky? Mask the grass.

The inputs you'll actually touch

  • no_of_colors (default 6) - the size of the extracted palette. Too low and you get a posterized, banded look; bump it toward 10-16 for photographic sources.
  • strength (default 1, range 0-2) - luminance preservation. This is the dial you'll actually fidget with.
  • gamma / contrast / brightness - the post pass; defaults are fine most of the time.

The output is a single image, ready to wire anywhere an IMAGE goes.

Installing it

The node ships in GeraldWie's ComfyUI-I2I-slim pack (a slimmer fork of ManglerFTW's ComfyI2I, minus the ComfyShop paint editor). Easiest route is ComfyUI Manager:

Manager → Install Custom Nodes → search "ComfyUI-I2I-slim" → Install → Restart

or the manual way:

cd ComfyUI/custom_nodes
git clone https://github.com/GeraldWie/ComfyUI-I2I-slim
cd ComfyUI-I2I-slim
pip install -r requirements.txt

One warning about that requirements file: it lists tensorflow and scikit-image, but the shipped code never imports either - they're leftovers. Installing the full list wastes a couple of gigabytes on a framework you don't need. The code actually runs on numpy, torch, torchvision, opencv and PIL. No model downloads needed for this node.

Common issues

  • Posterized output - no_of_colors is too low. Raise it.
  • Result looks washed out - that's strength drifting the luminance too far; pull it toward 1 or above to retain the target's lighting.
  • The original ComfyI2I color transfer was hard-coded to CUDA and simply broke on Apple Silicon - users were hand-editing cuda to mps in the source. This fork routes through device = 'cuda' if torch.cuda.is_available() else 'cpu', so it works on a Mac out of the box.

One honest caveat: this fixes hue, not light direction. If your pasted region still looks foreign after a transfer, the missing piece is usually shadows - that's a different node's job.

CategoryI2I-slim

Inputs (10)

NameTypeDefaultDescription
source_imageIMAGE
target_imageIMAGE
no_of_colorsINT60–256
blur_radiusINT20–100
blur_amountINT20–100
strengthFLOAT1.00–2
gammaFLOAT1.00.1–2
contrastFLOAT1.00–3
brightnessFLOAT1.00–100
maskoptMASK

Outputs (1)

NameTypeDescription
imageIMAGE