Nodes/ComfyUI_LC_MaskMaker_nodes/LC Auto Adjust πŸ”†
ComfyUI Node

LC Auto Adjust πŸ”†

The levels button ComfyUI never shipped

By lonecatone23Β·Created 26 days agoΒ·Updated about 18 hours agoΒ· 5
LC Auto Adjust πŸ”†
  • image
  • mask
  • image
β—„modeRGBβ–Ί
β—„strength100.0β–Ί
β—„brightness0.0β–Ί
β—„contrast0.0β–Ί
β—„saturation0.0β–Ί
β—„red0.0β–Ί
β—„green0.0β–Ί
β—„blue0.0β–Ί

You have an image that's fine except it's flat, and no node in stock ComfyUI fixes flat. So you do the thing everybody does: back to img2img with a low denoise, roll a new seed, watch the face change, and settle. This node exists so you don't have to. It's the Levels dialog from Photoshop, wearing a ComfyUI hat.

What it actually does

Auto levels. It measures the tonal range your image is actually using, then stretches it to fill 0–1. That's the whole trick, and it's deterministic - no model, no sampler, no seed lottery. Pure torch, no extra dependency, milliseconds.

The measurement is a 256-bin histogram of the pixels you selected. The stretch takes the lowest and highest bins that hold more than a bit of the population and maps them to black and white. Which pixels count as "selected" is where the modes come in.

The inputs you'll actually touch

mode picks what gets stretched:

  • RGB stretches each color channel on its own, which also kills color casts - a too-blue shot gets its blue channel pulled back into line.
  • lum + sat stretches saturation first, then luminance in Lab.
  • luminance moves brightness only and leaves hues where they are.
  • saturation stretches only the saturation channel.
  • mono stretches a black-and-white version, so you get a grey image out.

strength (0–100, 0.1 steps) blends the result back toward your original. It defaults to 100, and honestly 70–80 is often the nicer look if the full stretch is clipping highlights you cared about.

Then brightness, contrast, saturation, and per-channel red / green / blue balance - all applied after the levels, all in 0.1 steps, all defaulting to 0. Positive balance brightens that channel, negative darkens it; the gamma curve on the node is gentle near 0 and steepens fast past Β±50, so use small numbers. Balance is ignored in mono mode.

The one worth understanding: the optional mask. Per the author's own tooltip, it limits both where the levels are measured and where they land. Masking a face means the histogram is built from the face only, so skin gets stretched against skin and not against a bright window. That's different from what most people assume, and it's the reason the node is genuinely useful in a portrait workflow rather than a one-trick levels button. Wire a face mask from LC Person Mask or LC Create Mask and it becomes a targeted exposure fix. If your image already has an alpha channel and you connect nothing, that alpha is used as the mask.

Output is a single image. It's an ordinary IMAGE, so it goes wherever a preview, a save, or the next node wants it.

Where it sits in the workflow

Think of it as the layer that stops you throwing a diffusion pass at a job a lookup table does perfectly. Regenerating to fix a color cast costs you a seed, a face, and thirty seconds of GPU - and gets you a different image, not a corrected one. Reach for this first, and only escalate to a re-gen when the problem is actually content.

Its natural partner is LC Image Blend Advance: auto-adjust a cutout before compositing it, so it stands a chance of matching the background it's landing on. Note what this node does not do - it levels your subject against its own histogram, it doesn't match it to the background's statistics. That's a color-match job, and it's a different node's business.

Install

ComfyUI Manager, search LC MaskMaker (the registry name is "ComfyUI LC MaskMaker Nodes"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/lonecatone23/ComfyUI_LC_MaskMaker_nodes
# restart ComfyUI

Manager runs the pack's install.py, which only pip-installs packages that are missing and never touches torch, numpy or pillow. This node needs none of them anyway - it's torch-only, so it works even on a machine where the model-backed nodes in the pack are failing to load.

If it goes wrong

  • Your whites look blown after stretching. Expected - auto levels assume your image is under-using its range. Pull strength down toward 70 and take contrast slightly negative.
  • Colors shifted when you only wanted brightness. You're in RGB mode. Switch to luminance, which works in Lab and leaves chroma alone.
  • The masked result looks washed out compared to the unmasked one. The mask narrowed both the measurement and the application, so the stretch is computed from a smaller slice of tones. That's the feature; if you want a global stretch applied locally, that isn't what this does.
  • Mono still shows color. It shouldn't - mono expands a single grey channel to all three. If you're seeing color, you're looking at a downstream node's output.

One honest note on the pack itself: it's a single author's side project, not a famous node set, and it has essentially no discussion anywhere. What that buys you here is a small, readable, dependency-free node that does one deterministic thing - which is exactly what you want from the levels button.

CategoryLC MaskMaker/adjust

Inputs (10)

NameTypeDefaultDescription
imageIMAGEAn alpha channel, if there is one, is kept and used as the mask when no mask is connected.
modeCOMBORGBRGB: stretch each color channel on its own (also removes color casts). lum + sat: stretch saturation, then luminance. luminance: stretch brightness only, colors stay put. saturation: stretch saturation only. mono: stretch a black and white version.
strengthFLOAT100.00–100How much of the result is used, in percent.
brightnessFLOAT0.0-100–100Trim after the auto levels.
contrastFLOAT0.0-100–100Trim after the auto levels.
saturationFLOAT0.0-100–100Trim after the auto levels.
redFLOAT0.0-100–100Color balance: positive brightens the red channel, negative darkens it. Not used in mono mode.
greenFLOAT0.0-100–100Color balance for the green channel.
blueFLOAT0.0-100–100Color balance for the blue channel.
maskoptMASKLimits both where the levels are measured and where the result is applied.

Outputs (1)

NameTypeDescription
imageIMAGEβ€”