MLiang Color Correction
The one-node finishing pass that un-flats your generations without re-rolling
- image
- image
You know the feeling: the composition is exactly right, and the render still comes out slightly flat, a touch cool, a bit washed. The honest move is not to re-roll the seed - it's a two-minute color pass, and this node is that pass. MLiang Color Correction is a single IMAGE-in, IMAGE-out node with eleven sliders that does what you'd otherwise fire up Photoshop for: exposure, contrast, temperature, tint, shadows, highlights, the lot. No models to download, no extra Python packages, no GPU hit beyond a few tensor ops. It's the cheapest possible finishing step between your VAE decode and Save Image.
What it actually is
It's a deterministic pixel operation, not an AI anything. The whole pack - both this node and its white balance sibling - is one __init__.py of pure PyTorch. The author (dingmuliang, a Chinese indie dev who also maintains a LoRA browser pack) calls it "lightweight and pure," and that's not marketing: there's no requirements.txt, no model files, nothing to fetch. A gamma curve is a gamma curve, as the post-processing folks like to say - and this is a friendly wrapper around a whole stack of them.
That's also the context that matters when you're deciding whether you need it. The community's standing advice on this layer: reach for the cheap deterministic primitive before you burn a diffusion pass fixing color. Color correction with img2img is the classic overkill; a slider node does it in milliseconds, and it never rewrites a face or re-rolls your seed lottery.
How it works
Read the source and the order of operations is right there, and the order matters:
exposuremultiplies by2^exposure, so +1 is literally one f-stop. This is your main lever and the one you'll use most.brightnessadds a constant offset to every pixel. Additive, which means it flattens contrast and clips highlights fast - prefer exposure or gamma.contrastscales around the 0.5 midpoint (a classic pivot, not a curve).temperature/tintare channel multipliers - warm pulls red up and blue down, tint swings green vs magenta.saturationblends toward luma using Rec.709 weights rather than a naive average, so it doesn't nuke luminance.hue_shiftrotates hue in degrees via an RGB→HSV→RGB round trip. Handy, rarely needed.shadows/highlightsbuild masks from squared luma, so they push dark regions and bright regions without a full curve.gammais apow(x, 1/gamma)curve - lifts shadows without moving white.strengthblends the corrected result back into the original. 0 = untouched, 1 = full correction.
Everything clamps to 0–1 at the end, and if your image carries an alpha channel it's passed through untouched. All defaults are neutral (zeros and ones), so wiring the node in changes nothing until you move something.
The inputs that matter
Eleven sliders is a lot of knobs. For a beginner, four do 90% of the work:
- exposure - the f-stop dial; first thing to reach for on anything too dark or too bright.
- contrast - 1.0 is neutral; 1.1–1.2 un-flats most washed-out renders.
- temperature - warm it up or cool it down when the model's white balance is off.
- strength - the safety net. Dial in a subtle grade at 0.3–0.5 instead of a full-on repaint.
Everything else is seasoning. The single output image wires straight into Preview Image or Save Image, or into further post-processing further down the graph.
Installing it
ComfyUI Manager can grab it - search "mliang" or "color correction" - or clone it by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/dingmuliang/comfyui_mliang_color_correction.git
Then restart ComfyUI. That's the whole install: no model downloads, no pip step, no install.py to worry about. The only moving part is the Python file itself.
Where it bites
The output clamps hard at 0–1, and there's no tone mapping. Push exposure or brightness far and you get ugly clipped highlights, not a gentle rolloff - the spacepxl Exposure Adjust node has tonemapping if that's what you need. brightness is additive, so it's the fastest way to wash an image out; gamma does the same job without wrecking the top end. And remember this is sRGB-encoded space, not scene-linear - it's final-polish tooling, not a substitute for a real OCIO pipeline if you're feeding a VFX comp.
Worth knowing before you commit: this is a tiny, early-stage pack (a single commit, one star, a WeChat Pay tip jar in the README). There's essentially zero community discussion of it, so you're on your own for taste - but the sliders are honest, and for "make this render look less flat" it's genuinely hard to beat.
Inputs (12)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| exposure | FLOAT | 0.00-5–5 | — |
| brightness | FLOAT | 0.00-1–1 | — |
| contrast | FLOAT | 1.000–3 | — |
| saturation | FLOAT | 1.000–3 | — |
| gamma | FLOAT | 1.000.1–5 | — |
| temperature | FLOAT | 0.00-1–1 | — |
| tint | FLOAT | 0.00-1–1 | — |
| hue_shift | FLOAT | 0-180–180 | — |
| shadows | FLOAT | 0.00-1–1 | — |
| highlights | FLOAT | 0.00-1–1 | — |
| strength | FLOAT | 1.000–1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |