Apply CDTuner
Fix the fried look — contrast and detail without leaving the graph
- model
- MODEL
The "deep fried" look - oversaturated, crunchy, blown-out colors - shows up when you push CFG on a speed-LoRA model (Hyper SDXL, Lightning) or on any checkpoint that runs hot. The classic A1111-era answer was hako-mikan's sd-webui-cd-tuner, and Apply CDTuner is its ComfyUI port. One model input, a few sliders, and it adjusts the UNet's contrast and detail during generation itself, instead of hoping post-processing fixes it.
What it does
CDTuner clones your model and wraps its UNet forward pass. During the sampling steps you select, it temporarily rescales a handful of specific tensors - the first input convolution's weight and bias, the final output convolution's weight and bias, and the output GroupNorm's bias - then restores them after every step. Because it patches weights per-step rather than massaging pixels afterward, it changes how the model draws, not what the result looks like after a filter.
The dials, from the author's own schema:
detail_1- scales the first input conv's weight down and bias up. This is the "amount of writing / detail" control.detail_2- the same idea applied on the output side of the UNet.contrast_1- nudges the output GroupNorm's bias, which shifts contrast.start/end- which portion of the denoising range the adjustment applies to.
A note on confidence: the code comments are literally hedged with "…?" - the author knows what the sliders do roughly, not exactly. Treat them as "turn one, look, repeat" rather than precision instruments. The time-tested recipe from the A1111 days: when a low-step SDXL speed LoRA gets fried at higher CFG, a small contrast tweak here pulls it back toward usable.
The one trap: start/end are timesteps, not steps
The README calls this out directly: start and end live in the 0–1000 timestep coordinate, not sampler steps. Set end: 20 thinking "last 20 steps" and you've actually told it to act only on the noisiest timesteps - the very start of generation. Defaults are 0 and 1000, which means the whole run, and that's the right place to start for most people. The active window is wherever the timestep falls between 1000 - end and 1000 - start, so if you want an effect late in the process, think in terms of that inverted range.
Inputs and outputs
model(MODEL) - the only required input beyond the slidersdetail_1,detail_2(FLOAT, −10 to 10, default 0) - normal playing range is small, 0.1 to 1.0contrast_1(FLOAT, −20 to 20, default 0)start,end(INT, 0 to 1000, defaults 0 and 1000)- Output:
MODEL, straight into your KSampler
Everything defaults to identity (all zeroes), so dropping the node into a graph changes nothing until you actually dial something in.
Install
Same pack as Apply Negapip - one clone, two nodes:
cd ComfyUI/custom_nodes
git clone https://github.com/laksjdjf/cd-tuner_negpip-ComfyUI
or search "cd-tuner" in ComfyUI Manager, then restart. No dependencies, no model files.
What it's not
The README is upfront that this is a partial port - "only some features implemented" of the original extension. It's also built around classic U-Net tensor names (input_blocks.0.0, out.0, out.2), which means SD1.5 and SDXL-lineage checkpoints. A Flux-style transformer architecture has no such tensors, so expect silence or an error there, not a result. This is a tool for the big-batch anime and photoreal SD world where people actually hit the fried-look problem, and it's a small, opinionated one - but when that's your problem, it's the direct fix.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| detail_1 | FLOAT | 0.0-10–10 | — |
| detail_2 | FLOAT | 0.0-10–10 | — |
| contrast_1 | FLOAT | 0.0-20–20 | — |
| start | INT | 00–1000 | — |
| end | INT | 10000–1000 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| MODEL | MODEL | — |