Match Brightness Contrast
Make one image's light match another's — and keep it stable across frames
- source_image
- reference_image
- image
Two images, one of them looks wrong next to the other - too dark, too flat, different exposure. Match Brightness Contrast drags the source image's brightness and contrast toward a reference image's, per color channel, so a generated frame can sit in a scene without looking pasted-on. It's the color-timing tool you reach for when a composite keeps failing on light, not on geometry.
How it works
Two methods, both operating per RGB channel. histogram (default) builds per-channel cumulative histograms of source and reference, then maps each source brightness level through the reference's distribution - the standard histogram-matching approach that reshapes the whole tonal curve, not just the average. standard is the cheaper statistical route: it measures each channel's mean and standard deviation on both images and applies (x - mean_src) * (std_ref / std_src) + mean_ref - a mean/std color transfer. Histogram is more faithful; standard is lighter.
The clever bit is edge_amount. A margin of the image (default 20% of the short side) can be used for the statistics instead of the whole frame. Why? Because if your two images show different content in the middle but the same lighting at the edges, measuring only the borders keeps the match about exposure rather than about whatever's in the center. edge_amount under 1.0 is a fraction of the short side; 1.0+ is raw pixels; 0 means use everything.
consistency exists for batches and video. frame_match recalculates per frame. The others - lock_first, lock_mid, lock_end - compute the mapping once from a chosen frame pair and apply that same mapping to every frame. That's the anti-flicker setting: recalculating per frame makes each frame individually match, but the amount of correction drifts and you get pulsing. Locking kills the drift.
The inputs that matter
- source_image / reference_image (
IMAGE) - what gets corrected / what it's corrected to. - edge_amount (
FLOAT, default 0.2) - border-only statistics fraction. The one you'll tune first. - method -
histogramorstandard. - consistency -
lock_first(default),lock_mid,lock_end, orframe_match.
Output: image (IMAGE), the corrected source.
Installing it
ComfyUI Manager → search ComfyUI-1hewNodes → install → restart, or:
cd ComfyUI/custom_nodes
git clone https://github.com/1hew/ComfyUI-1hewNodes
Restart ComfyUI. Pure tensor math, no model downloads. Pack pulls heavy requirements regardless (rembg, ultralytics, etc.), and it needs a current ComfyUI for its comfy_api.latest API.
Common issues
Batch mismatch is handled gracefully - if your source has 24 frames and the reference has 1, frames just cycle through the reference - but it means you should make sure the intent matches too. Watch the consistency trap: the default lock_first computes from frame 0, so if frame 0 is an outlier (a flash frame, a near-black frame), every frame gets corrected against that bad sample. And edge matching assumes your subjects are center-weighted; a subject that runs to the canvas edge will pollute the border statistics, so widen edge_amount or use the full frame.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| source_image | IMAGE | — | |
| reference_image | IMAGE | — | |
| edge_amount | FLOAT | 0.200–8192 | — |
| consistency | COMBO | lock_first | 4 options: lock_first, lock_mid, lock_end, frame_match |
| method | COMBO | histogram | 2 options: standard, histogram |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |