Nodes/Immac's Tools/Match Contrast
ComfyUI Node

Match Contrast

Make one image's contrast match another — deterministically, no re-gen

By Immac·Created 11 months ago·Updated 6 months ago· 0
Match Contrast
  • image
  • reference
  • image
channel_modeluminance
strength1.00

Match Contrast takes one image and reshapes its tonal distribution to match a reference image's. Not a lazy brightness slider - a full histogram match, which is the deterministic way to say "make these two pictures sit in the same light." It's the kind of tool you reach for after you've composited, inpainted, or upscaled, when a region refuses to blend into its surroundings.

Here's the mental model. The node builds a histogram of both images and aligns them by cumulative distribution - every brightness level in your image gets mapped to the reference level that has the same fraction of pixels below it. It quantizes to 65,536 levels, which is more precision than you'll ever notice, and applies the mapping as a lookup table. Because it's histogram matching rather than mean/std transfer, it matches the shape of the reference's tones, not just its average - a properly exposed but flat source matched to a high-contrast reference comes out high-contrast.

The inputs that matter:

  • image - what gets adjusted.
  • reference - whose tonal distribution is the target.
  • channel_mode - the one real choice. luminance (default) converts to CIE LAB and matches only the L channel, so it changes brightness and contrast while keeping your image's colors intact. rgb matches each R/G/B channel independently, which also pulls the color palette toward the reference.
  • strength - blend from the original (0.0) to the fully matched result (1.0), default 1.0. Crank it down when a full match is too aggressive.

One IMAGE output, ready for a save or a compositor. Matching is done per-frame, and if the reference has fewer frames than the image, the reference's first frame is reused for the rest - handy for matching a whole batch to a single target.

The uses line up with the standing advice in the post-processing world: don't re-generate to fix color. An inpainted or outpainted region that doesn't match the original, an upscaled tile that fights its neighbors, a composited subject that floats in a new background's light - this is the cheap deterministic fix. It's also a genuinely good one-two punch for grading: match contrast with luminance, then reach for a color-transfer node if the palette itself needs pulling.

Installing it

Part of ComfyUI-ImmacTools by Immac - MIT-licensed, and note this is the rare node in the pack that does its work with pure numpy (a small hand-rolled sRGB↔LAB pipeline), so it needs nothing beyond what ComfyUI already bundles. No models, no downloads. ComfyUI Manager by repo URL, or:

cd ComfyUI/custom_nodes
git clone https://github.com/Immac/ComfyUI-ImmacTools

Restart ComfyUI. It's the one node filed under image/adjust, so search "Match Contrast" or "Immac". Current ComfyUI required (ComfyExtension API).

Common issues

Two practical notes. First, performance: the per-frame work happens in numpy on CPU, so a long video batch will be noticeably slower than a GPU-native node - for a still or a handful of frames it's instant. Second, matching is per-frame, not cross-batch, so if your reference batch is short, frame 0 anchors the whole match; make sure that first frame is actually the look you want. And the usual image-node caution: both images should be in the same-ish exposure territory. Histogram matching can't invent dynamic range - it can only redistribute the range you already have, and the result clips if your source is already crushed.

Categoryimage/adjust

Inputs (4)

NameTypeDefaultDescription
imageIMAGE
referenceIMAGE
channel_modeCOMBOluminancergb: match each R/G/B channel independently. luminance: match only the L channel in CIE LAB (keeps source colours, adjusts brightness/contrast).
strengthFLOAT1.000–1Blend between the original image (0.0) and the fully matched image (1.0).

Outputs (1)

NameTypeDescription
imageIMAGE