Adjust Contrast
The one-knob contrast slider hiding inside ComfyUI's training pipeline
- images
- images
This looks like a post-processing node and reads like one - image in, image out, a contrast slider. It isn't. Adjust Contrast shipped inside ComfyUI's dataset-processing pipeline (comfy_extras/nodes_dataset.py, part of the improved built-in LoRA trainer release, late 2025), and its honest job is batch-prepping training data, not grading your final render. It does that job fine, though, because underneath it's two lines of tensor math with a single knob.
What it actually does
Every channel of every pixel gets scaled around mid-gray:
return ((image - 0.5) * factor + 0.5).clamp(0.0, 1.0)
That 0.5 is the pivot. A factor of 1.0 is a no-op. Below 1.0 pulls everything toward flat gray - 0.0 turns the whole image into featureless mid-gray. Above 1.0 pushes highlights up and shadows down, so the light/dark gap widens. This is linear contrast, not a gamma curve or an S-curve: no shadow-versus-highlight control, no perceptual curve, nothing fancy. It's a blunt instrument, and it knows it.
The inputs that matter
Only two, and only one you'll touch:
- images (IMAGE) - what you're adjusting.
- factor (FLOAT, 0–2, default
1.0) - the whole show.1.0= no change,<1.0= less contrast,>1.0= more.
Output is images (IMAGE), so it chains into anything that takes an image - including the sibling Adjust Brightness node right next to it in the same category. Image → Adjust Contrast → Save Image is a complete graph.
It's flagged is_experimental and marked as pure tensor math, which means it handles any batch size in one pass and even treats a video tensor like a batch. No per-frame loop, no slowdown on long lists.
Where it fits, and where it doesn't
The intended flow is dataset prep: LoadImageDataSetFromFolder → Adjust Contrast → SaveImageDataSetToFolder, to flatten tonal variation across a training set before captioning. Consistent exposure matters in training data - the LoRA-training literature is unanimous that dataset curation beats every tuning knob, and "some images washed out, some muddy" is exactly the kind of inconsistency you'd rather delete than train around.
For polishing a finished render, it's a worse fit. The photorealism consensus is that AI output already trends toward too much contrast - you usually want to pull it down a touch, which factor 0.85–0.95 does fine. But this node can't touch saturation or color cast, which is where half of the "AI look" lives, so a real grade still means a post-processing pack or an editor.
Where people get burned
- Clipping is permanent. Values are clamped to
[0,1]. Crank toward2.0and anything brighter than ~0.75 luminance goes to pure white, anything darker than ~0.25 goes to pure black - detail gone, unrecoverably, and the node has no undo pass. Keep moves small;0.85–1.15is the useful band. - It's experimental and young. Barely anyone has posted about it, there aren't many example workflows, and the schema could shift. Fine for personal graphs; don't hard-code it into something you ship without pinning a ComfyUI version.
- No install, no model files. It ships with core - type "contrast" in the node search and it's there. Nothing to download, nothing to configure.
Reach for it when you're building a data-prep graph or want one dumb contrast knob inline. For graded final output, keep walking.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | Image to process. | |
| factor | FLOAT | 1.000–2 | Contrast factor. 1.0 = no change, <1.0 = less contrast, >1.0 = more contrast. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | Processed images |