Nodes/WAS Node Suite v3/Image Auto Levels
ComfyUI Node Runs on cloud

Image Auto Levels

The one-click contrast fix — levels that measure themselves

By WASasquatch·Created 3 years ago·Updated 4 days ago· 1,844
Image Auto Levels
  • images
  • images
  • black_point
  • white_point
method
clip_low0.0010
clip_high0.0010
strength1.00

A flat render, a hazy plate, a washed-out scan - they all share the same problem: the image's tones don't actually use the range they're allowed. If nothing in the frame is darker than 20% grey and nothing brighter than 80%, the picture reads as grey and flat no matter how good the content is. The classic fix is levels: set a black point, set a white point, and stretch everything between to fill the range. The classic annoyance is that you have to look at the image and guess where those points should be.

Image Auto Levels removes the guessing. It measures where the frame's tones actually start and stop - finds the real black and white points in the data - and stretches the frame to fill the range. Flat render in, contrast out, nothing set by hand. That's the whole node, and it's a genuinely good default when you want "make this less washed out" without thinking about it.

How it works

The measurement is the mechanism, and the settings are all about protecting that measurement from liars:

  • method - on brightness stretches all three channels by the same amount, keeping the colour as it was - pure contrast. per channel stretches red, green and blue separately, which adds contrast and pulls out a colour cast at once. Hazy or flat → on brightness; hazy and bluish → per channel.
  • clip_low / clip_high - the share of the darkest and lightest pixels allowed to go fully black/white. This is the subtle but crucial knob. 0.0 means the single darkest pixel sets the black point - so one stuck pixel, one dust speck, one specular hit ruins the whole stretch. The default 0.001 ignores that thousandth of extreme pixels; 0.02 gives a deeper, more aggressive crush. If your image is a render, you almost never want 0.0.
  • strength - how far toward the stretched result the frame moves. 1.0 is the full stretch, 0.5 is halfway, 0.0 is untouched. When full stretch looks too crunchy, this is the dial that keeps the measured points but backs the effect off.

The batch behavior is quietly excellent: the whole batch is measured together, so a sequence of frames gets one consistent stretch rather than each frame flickering as its own measurements wobble. For video, that's the difference between a working grade and a strobing mess.

What comes back

Besides the images output, the node tells you what it found: black_point and white_point are the brightnesses the stretch read as black and white, on a 0-to-1 scale. white_point of 0.6 means the frame was two-fifths short of white before you fixed it; a value of 1.0 means it already reached white and there was nothing to gain. Wire those into a log, or just read them to know whether the node actually had work to do.

Installing it

WAS Node Suite v3, standard: ComfyUI Manager → search WAS Node Suite v3, or clone into custom_nodes, restart. No weights, no dependencies - it's a histogram measurement and stretch, running on torch.

Where does it fit versus the rest of the toolbox? This is the automatic version of what WAS Image Levels Adjustment does with two points you type in, and it belongs to the same deterministic post-processing family as gamma and sigmoid curves - instant, millisecond, no diffusion pass. Reach for it first on flat or hazy frames, add a gamma or curve on top when you want character, and save your re-rolls for problems that actually need a model. Auto Levels is where you start, not where you stop - but it's a very good start.

CategoryWAS Suite/Image/Adjustment

Inputs (5)

NameTypeDefaultDescription
imagesIMAGEThe frames to stretch. The whole batch is measured together, so a sequence keeps a steady exposure rather than flickering frame to frame.
methodCOMBO`per channel` stretches red, green and blue separately, which adds contrast and neutralises a cast at once; `on brightness` stretches all three by the same amount, which keeps the colour as it was.
clip_lowFLOAT0.00100–0.2Share of the darkest pixels allowed to go fully black. 0.0 = the single darkest pixel sets the point, so one stuck pixel ruins it; 0.001 = a thousandth, which ignores those; 0.02 = a deeper crush.
clip_highFLOAT0.00100–0.2Share of the lightest pixels allowed to go fully white. 0.001 = a thousandth, which ignores a specular hit; 0.02 = brighter, with more of the highlight blown.
strengthFLOAT1.000–1How far towards the stretched result the frame moves. 1.0 = the full stretch, 0.5 = halfway, 0.0 = the frame untouched.

Outputs (3)

NameTypeDescription
imagesIMAGEThe stretched frames.
black_pointFLOATThe brightness the stretch read as black, on a 0 to 1 scale. 0.0 = the frame already reached black and nothing was gained below.
white_pointFLOATThe brightness the stretch read as white, on a 0 to 1 scale. 1.0 = the frame already reached white; 0.6 = it was two fifths short.