Nodes/radiance/HueCorrect
ComfyUI Node

HueCorrect

Hue-vs-hue curves, except you type the curve as JSON

By FXTD-Studios·Created 8 months ago·Updated about 18 hours ago· 246
HueCorrect
  • image
  • image
  • grade_info
◄modeHue vs Hue►
◄control_points[[0.0,0.0],[0.167,0.0],[0.333,0.0],[0.5,0.0],[0.667,0.0],[0.833,0.0],[1.0,0.0]]►
◄strength1.00►
◄grade_info—►

If you've graded in Resolve or Nuke you know HueCorrect: a curve where the x-axis is hue and the y-axis is how much to shift that hue. It's the tool for the things global colour adjustments can't do - pulling the green out of foliage without touching the greens in someone's shirt, or shifting a whole range of skin tones without moving the oranges in the background.

Radiance's version does the same job. The one thing you need to know before you touch it is that there's no draggable curve widget. You type the control points as JSON.

How it works

You supply a list of [hue, amount] pairs, hue running 0 to 1 around the wheel (0 red, 0.333 green, 0.667 blue, 1 back to red). The node interpolates piecewise-linearly between them. Whatever amount your hue resolves to gets added - the sign and meaning depend on mode:

  • Hue vs Hue - amount is a hue rotation measured in turns, so 0.05 nudges that colour about 18° round the wheel.
  • Hue vs Saturation - amount is an HSL saturation delta.
  • Hue vs Luminance - amount is an HSL lightness delta.

The default control_points are all zeroes, which is why a fresh node does nothing at all. That's not broken; that's a flat curve.

Then the HDR handling, which is the bit that makes this Radiance's node rather than a generic one: pixels whose luma is above 1.0 are normalised down for the HSL conversion, and rescaled afterwards. HSL maths on a value of 12.0 would produce garbage; scaling it down, doing the hue work, and scaling back keeps highlight colour intact. There's a comment in the source about a previous version where a typo in the JSON silently fell back to a flat curve - unchanged output, no message. In 3.5.0 a curve that doesn't parse raises an error. Say what you like about the failure mode, it's better than silence.

Inputs and outputs

Required: image (RGB in any encoding), mode, control_points (the JSON string), strength (0–2 multiplier on every amount; use it as a wet/dry fader while you're dialling in, or explicitly set it to 0 to kill the adjustment without losing your curve).

Optional: grade_info, a string input that the node doesn't use for the maths but copies into the upstream field of its own output - so a chain of grading nodes keeps a record of what was done. Wire it if you're building an auditable grade chain; ignore it otherwise.

Outputs: image and grade_info.

A worked example, if the JSON is putting you off. To push greens slightly toward yellow and desaturate blues a touch:

[[0.0,0.0],[0.25,0.03],[0.333,0.05],[0.5,0.0],[0.667,-0.1],[0.833,0.0],[1.0,0.0]]

With mode = Hue vs Hue that rotates hues near green by up to 0.05 turns; switch to Hue vs Saturation with the same points and you're desaturating instead. Same curve, different axis, which is a nice property when you're auditioning which correction the shot actually wants.

Installing Radiance

Manager → search Radiance → install → restart → refresh. Manual:

cd ComfyUI/custom_nodes
git clone https://github.com/fxtd-studios/radiance.git
cd radiance
python -m pip install -r requirements.txt

Windows portable: use python_embeded\python.exe. No weights for this one. The pack (GPL-3.0, ~147 visible nodes, FXTD Studios) installs OpenEXR, OpenImageIO, OpenColorIO, diffusers and accelerate into ComfyUI's Python environment.

Troubleshooting

Nothing happens. Check three things in order: is strength above 0, are any amounts non-zero, and does your image actually contain the hues your points target? A curve peaking at hue 0.333 does nothing on a photo of a red wall.

"Invalid JSON" or an error on run. Trailing commas are the usual culprit. It's strict JSON, not Python. The node also accepts a flat list ([0,0, 0.25,0.03, ...]) which it pairs up internally, so a missing bracket can slip through as malformed pairs - read the error rather than assuming the node is broken.

Only part of the image shifted. Expected: you're targeting a hue range. Widen the curve's skirt, or add intermediate points, if the transition into untouched hues looks banded.

Colours look wrong in deep shadows. HSL on near-black pixels is numerically unstable - hue is meaningless when there's no colour. Grade the shadows before the curves, or lift them slightly first.

Where this doesn't belong. If your problem is "the whole image is off compared to a reference", a statistics-based colour match is the right tool, not a hue curve. HueCorrect is for selective, deliberate moves.

CategoryFXTD STUDIOS/Radiance/Color

Inputs (5)

NameTypeDefaultDescription
imageIMAGEImage to adjust, RGB in any encoding. Pixels with luma above 1.0 are normalised for the HSL conversion and rescaled afterwards.
modeCOMBOHue vs HueWhat the curve's output changes for each input hue: hue rotation, HSL saturation, or HSL lightness.
control_pointsSTRING[[0.0,0.0],[0.167,0.0],[0.333,0.0],[0.5,0.0],[0.667,0.0],[0.833,0.0],[1.0,0.0]]JSON list of [hue, amount] points, hue 0 to 1 (0 red, 0.333 green, 0.667 blue, 1 red again). Amount is added: hue shift in turns, or a saturation or lightness delta; 0 everywhere (the default) changes nothing.
strengthFLOAT1.000–2Multiplier on the curve's amounts. 0 = no change, 1 = as drawn, 2 = doubled.
grade_infooptSTRINGUpstream grade metadata. Not used for the adjustment; stored as the 'upstream' field of the grade_info output.

Outputs (2)

NameTypeDescription
imageIMAGE—
grade_infoSTRING—