Donut Image Adjust
Six tone and color fixes, one node
- image
- image
- gamma
If you've poked at this pack at all, you've seen the graveyard: DonutGammaCorrection, DonutAutoGamma, DonutAutoWhiteBalance, DonutHistogramStretch, DonutHiRaLoAm, DonutCAS - six image nodes, all marked DEPRECATED. DonutImageAdjust is why. It folds all six operations into a single node behind one operation dropdown, with each operation's parameters namespaced and tucked into the optional block so unused ones never get in your way. This is the node to reach for; the standalone six are kept alive purely so old workflows keep loading.
It's a post-processing workhorse, and the nice thing is how deliberately it's built: every operation reuses the original implementation verbatim - no math was re-implemented, so a local_contrast here is byte-for-byte the old DonutHiRaLoAm.
The operations
auto_gamma- detects the exposure and corrects it. Methods:simple_mean(fastest),iagcwd,gslf(histogram-based, "most sophisticated"), andpercentile(robust to outliers). Addag_strength,ag_target, andag_direction(both / brighten_only / darken_only) to steer it.gamma- the power-curve midtone fix.gm_gammafrom -100 to +100 (positive lifts shadows), plusgm_ditherto break up banding.white_balance- color-cast removal viawb_method:gray_world,white_patch,combined,auto_levels, orphotoshop(per-channel plus midtone snap).wb_strengthandwb_clip_percentcontrol the aggressiveness.histogram_stretch- auto-levels, withhs_black_point/hs_white_pointpercentiles andhs_mode(global / per_channel / luminance).local_contrast- the Clarity-style boost (lc_radius,lc_amount,lc_protect_tones,lc_fast_blur).cas- Contrast Adaptive Sharpening (cas_sharpness,cas_contrast).
The namespacing means you can pre-tune every operation's widgets and switch between them by flipping one dropdown, which is genuinely handy for A/B comparisons on a fixed seed.
The outputs
Two outputs. image is the processed frame. The gamma FLOAT is the diagnostic from auto_gamma - the average gamma it measured, which is genuinely useful feedback when you're dialing in ag_target. For every other operation it's a flat 1.0, so don't build logic on it unless you're in auto_gamma.
Install
Standard pack install:
cd ComfyUI/custom_nodes
git clone https://github.com/DonutsDelivery/ComfyUI-DonutNodes.git donutnodes
cd donutnodes
python -m pip install -r requirements.txt
or ComfyUI Manager → "DonutNodes," then restart. No extra models to download - it's pure tensor math, so it runs on the CPU if it has to.
The trap to avoid
The classic post-processing mistake the KB calls out: reaching for img2img to fix contrast when a deterministic pass does it in milliseconds without a seed lottery. These operations are the "proper" fix - gamma, not brightness, for exposure (additive brightness flattens and clips), luminance-mode histogram stretch for flatness, and low-amount local contrast for depth. Chain them: stretch, then gamma, then a touch of CAS, and you've got the whole finishing kit in one node.
Inputs (21)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| operation | COMBO | gamma | Which image adjustment operation to apply. |
| ag_methodopt | COMBO | gslf | Detection method: simple_mean (fastest), iagcwd (deviation-based), gslf (histogram-based, most sophisticated), percentile (robust to outliers) |
| ag_strengthopt | FLOAT | 1.00–2 | Correction strength (1.0 = full correction) |
| ag_targetopt | FLOAT | 0.500.1–0.9 | Target value for simple_mean and percentile methods |
| ag_percentileopt | FLOAT | 501–99 | Which percentile to target (percentile method only) |
| ag_directionopt | COMBO | both | both: auto brighten/darken, brighten_only: only brighten dark images, darken_only: only darken bright images |
| gm_gammaopt | FLOAT | 0-100–100 | Gamma adjustment (-100 to +100). Positive brightens shadows, negative darkens them. |
| gm_ditheropt | FLOAT | 0.00–2 | Dither amount to reduce banding (0 = off, 0.5 = subtle, 1.0 = 1 LSB worth of noise) |
| wb_methodopt | COMBO | gray_world | gray_world: shift means to gray. white_patch: scale by brightest. combined: both. auto_levels: per-channel stretch (Auto Tone). photoshop: per-channel + midtone snap (Auto Color) |
| wb_strengthopt | FLOAT | 1.00–2 | Correction strength (1.0 = full correction) |
| wb_clip_percentopt | FLOAT | 0.10–10 | Percent of pixels to clip from brightest/darkest (Photoshop default: 0.1%) |
| hs_black_pointopt | FLOAT | 0.00–49 | Percentile for black point (0 = absolute min, 1+ = robust) |
| hs_white_pointopt | FLOAT | 100.051–100 | Percentile for white point (100 = absolute max, 99- = robust) |
| hs_modeopt | COMBO | luminance | global: bounds from luminance, same stretch to RGB (preserves ratios). per_channel: stretch RGB independently (may shift colors). luminance: LAB L-only (preserves hue/saturation, matches LayerStyle) |
| lc_radiusopt | FLOAT | 201–200 | Large radius for local contrast enhancement |
| lc_amountopt | FLOAT | 0.200–1 | Keep low to avoid halos (0.1-0.3 typical) |
| lc_protect_tonesopt | FLOAT | 0.00–1 | Protect shadows/highlights from clipping |
| lc_fast_bluropt | BOOLEAN | true | Use separable blur (faster, identical quality) |
| cas_sharpnessopt | FLOAT | 0.500–1 | Sharpening strength |
| cas_contrastopt | FLOAT | 0.0-1–1 | Contrast adjustment (0 = neutral) |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| gamma | FLOAT | — |