Local Contrast
The midtone pop that global contrast can't give you
- image
- mask
- image
- mask
- local_contrast_info
Global contrast is blunt: pull the slider and the whole image hardens, shadows crush, highlights clip, and you've spent your entire range to make the midtones marginally punchier. Local contrast is the surgical version - it adds contrast within small neighborhoods, so texture and depth pop while the overall tone curve stays untouched. It's the "clarity" slider in every photo editor, and it's the difference between an image that's contrasty and one that looks structured. Local Contrast is the MKRShift node for exactly that.
It's in MKRShift Nodes/Color/Grade, the pack's grading lane. It's the deterministic alternative to the classic generative mistake: re-rolling a seed because the image "looks flat" when a clarity pass would have fixed it in milliseconds. The KB's post-processing doc hammers this exact point - know which primitive does which job, and don't burn a diffusion pass on a curve.
How it works
It's a refined unsharp mask: blur a copy of the luma by radius (default 28 - the neighborhood size that defines "local"), subtract it from the original to isolate the local deviation, and add that deviation back scaled by amount (0.55). Where it gets more interesting than a plain clarity slider:
shadow_weight(0.7) andhighlight_weight(0.55) - how strongly the effect applies in the shadows and highlights. This is the control global clarity lacks: you can build structure in the shadows without sharpening the highlights into halos, or vice versa.midtone_boost(0.7) - a focused boost in the midtone band, where "pop" actually lives.preserve_luma(on) - applies the contrast to luma only and rebuilds color around it, so you get structure without shifting saturation or hue. This is the setting that keeps a clarity pass from turning into a color change.
mix (1.0) blends the whole effect, and the optional mask input scopes it to a region - the move for "give the face structure but leave the background alone."
Outputs and using it
The settings-JSON bundle gives you the knobs above plus mask_feather/invert_mask. Outputs: the finished image, a mask of the affected region, and a local_contrast_info string.
Where it shines: product shots (texture on fabric, wood, metal), skin (a light pass gives micro-texture without the plastic look), and any flat render before you hit it with the real grade. It's also a great first step - local contrast first, then global curves, because the global pass won't have to work as hard.
Installing it
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
then restart, or search MKRShift_Nodes in ComfyUI Manager. No pip requirements, no model downloads.
The failure mode is halos: when radius is too small relative to amount, the local-contrast band becomes a visible dark/light outline around edges - the same artifact as oversharpening. If you see halos, raise the radius before lowering the amount. And remember preserve_luma is doing real work - flip it off once to see how much color shift you're avoiding, then never touch it again.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| settings_json | STRING | {"radius":28.0,"amount":0.55,"shadow_weight":0.7,"highlight_weight":0.55,"midtone_boost":0.7,"preserve_luma":true,"mix":1.0,"mask_feather":12.0,"invert_mask":false} | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| local_contrast_info | STRING | — |