LC Tone Match
Put the original light back on your refined frame
- image
- reference
- mask
- image
Here's the workflow: you generate a frame, run it through a refinement/edit pass - a Krea2 or Qwen re-render, a face fix, an H3 video frame that drifted - and the result has better detail but the lighting went sideways. The shadows are in the wrong place, the white balance wandered, the whole thing no longer sits in the same scene as the rest of your clip. LC Tone Match is the fix: it takes your refined image and your original reference, and stitches them together by frequency - the reference keeps the broad lighting and color, the refined image keeps the micro-detail. Same job as ComfyUI's native H3 Detail Tone Lock, but for any two images, not just H3 outputs.
It's a post-processing node, not a model, which is exactly the argument this whole layer makes: a deterministic frequency blend costs milliseconds and doesn't re-roll your face. When your edit already looks great except for the light, you don't re-generate - you lock the tone.
How it works
Under the hood it's a blur-and-mix, the same DNA as unsharp masking but aimed at color instead of sharpness. Both images get Gaussian-blurred at detail_radius; the blur carries the broad tone (lighting, ambient color), and subtracting it leaves the fine detail. Then:
tone_match(default 0.85) pushes the refined image's broad tone toward the reference's - 0 means off, 1 is full lock.refinement_strength(default 0.55) decides how much of that tone-locked result actually gets mixed back over the reference. Lower it to avoid identity drift when the edit changed more than light.detail_radius(default 32) sets the blur that splits "broad" from "fine". The author's guidance: ~32 for a 1–2 MP image; go bigger for higher resolution.skin_protect(default 0.5) holds the reference's skin hue after the lock, so a face doesn't take on the new color cast - the same idea as LC Color Match's skin protect.
The optional mask is where this earns its keep: white = apply the lock, black = keep the refined image untouched. The classic use is a head-swap or a region you edited on purpose - paint the new head black and it keeps its own color while the rest of the frame locks back to the scene.
Output is a single image, and because the node doubles as a preview node, you get an on-node wipe against the reference so you can see the lock before it hits your save node.
The three knobs that matter
- tone_match - how hard to pull the light back. Most edits want it high (0.8–1.0).
- mask - white locks, black keeps. This is the difference between "match the whole frame" and "match everything except the thing I fixed."
- detail_radius - up it with resolution. Too small and the "tone" starts dragging fine detail around; too big and the lock misses the shadows you wanted fixed.
Where people get burned
- Same crop, or nothing. The node aligns by position, not by content. If your reference and your refined image aren't the same crop, the blur regions don't line up and you get smeared tone. Reframe first.
- Head-swaps need the mask. Don't tone-match a swapped face and expect it to stay recognizably that face - mask off the new head (black) so the lock skips it.
- It's not a color-match substitute. LC Color Match does full-frame statistical color transfer (the Reinhard-style mean/std job from the post-processing world). Tone Match is a frequency lock - it restores the reference's broad lighting over your detail, not its exact palette. Reach for the right tool: palette off → Color Match; lighting off → this.
Install
It's part of LC123, which has no extra dependencies - install once, get all ~90 nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC123_nodes
or via ComfyUI Manager (search "ComfyUI_LC123_nodes"), then restart. No model downloads needed for this node - it's pure pixel math. The one layout trap to dodge: __init__.py must sit directly in the pack folder, not a nested ComfyUI_LC123_nodes/ComfyUI_LC123_nodes/; if you unzipped into an existing clone, move the inner files up a level.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The refined / generated image (Krea2, Klein, Qwen, etc.). High-frequency is taken from here. | |
| reference | IMAGE | Original / H3 still. Authority for size, broad lighting, and color. | |
| tone_match | FLOAT | 0.850–1 | How hard to restore source low-frequency lighting/color. 0 = off, 1 = full lock. |
| refinement_strength | FLOAT | 0.550–1 | How much of the tone-locked refine is mixed over the source. Lower = less identity drift. |
| detail_radius | INT | 322–64 | Blur radius splitting broad tone from fine detail. ~32 for 1–2 MP. |
| skin_protect | FLOAT | 0.500–1 | Hold reference skin hue after the lock (0 = off). Same idea as Color Match. |
| maskopt | MASK | White = apply lock. Black = keep image as-is (use for a new head / edited region). |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |