Hue/Saturation per Range
Push one color family without wrecking the rest of the shot
- image
- image
Selective color is the difference between a grade that looks applied and one that looks intentional. Global hue/saturation sliders change everything at once; selective color changes only the reds, or only the greens, and leaves the rest of the palette alone. JHPixelProHueSaturationRange is the pack's selective-color node, and it does the classic "HSL targeted range" move: pick a hue center, define a band around it, and shift hue or saturation only inside that band.
The mechanism is a soft hue-wheel mask. The node converts to HSV, builds a Gaussian-ish falloff around your hue_center with band_width as the half-width in degrees, then applies hue_shift (degrees of hue rotation) and sat_mult / sat_add (multiplicative then additive saturation) only where the mask is active. Two details in the README are worth remembering: grayscale pixels are excluded from the mask (hue is undefined at zero saturation), and V is never touched - the node only changes hue and saturation, so brightness stays exactly as it was.
The inputs that matter
hue_center(0–360): 0=red, 60=yellow, 120=green, 180=cyan, 240=blue, 300=magenta. Pick the family you're grading.band_width(default 30): half-width in degrees. 30° is a narrow isolated band, 60° a wider family, and 180° is the whole wheel - at that point it's just a global hue/sat adjustment with extra steps.hue_shift(-180–180): rotate the hue inside the band.sat_mult(0–2): saturation multiplier inside the band. 1.0 = unchanged, 0 = desaturate to gray, 2 = double.sat_add(-1–1): additive saturation offset after the multiply - handy for lifting a family that desaturated too far.
The bread-and-butter uses: tighten skin reds without touching a saturated red background, push foliage greens or sky cyans for commercial styling, or desaturate the yellows in a product shot. It also composes cleanly with the pack's LUT pipeline - the README explicitly suggests building secondary grades here before exporting to a .cube LUT. Output is a single image, same shape as input.
Install
ComfyUI Manager → search ComfyUI-JH-PixelPro, or:
cd ComfyUI/custom_nodes
git clone https://github.com/jetthuangai/ComfyUI-JH-PixelPro.git
cd ComfyUI-JH-PixelPro
pip install -r requirements.txt
Restart ComfyUI; it's under ComfyUI-JH-PixelPro/color. The pack needs ComfyUI ≥ 0.43.x, Python ≥ 3.10, plus kornia, mediapipe, opencv-python-headless, and scipy.
A couple of honest notes. First, hue band selection is fiddly when the color you're chasing sits near a boundary (e.g. a skin tone that reads orange-red) - if your band keeps catching adjacent families, narrow band_width before you start pushing hue_shift. Second, and this is the trap people hit with every selective-color tool: a small hue_shift on a narrow band is invisible, and a large one is surgical - the node can't fix what the mask didn't include, so check the band is actually covering the pixels you mean. Start narrow, verify on the preview, then widen only if you must. It's a quiet, dependable node - no models, no download, no drama. Just the most-used grading move in every colorist's book.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| hue_center | FLOAT | 00–360 | Hue center in degrees (0=red, 60=yellow, 120=green, 180=cyan, 240=blue, 300=magenta). |
| band_width | FLOAT | 300–180 | Band half-width in degrees. 30° = narrow band, 60° = medium, 180° = full wheel. |
| hue_shift | FLOAT | 0-180–180 | Shift hue inside the selected band by this amount (degrees). |
| sat_mult | FLOAT | 1.000–2 | Multiply saturation inside the band. 1.0 = unchanged, 0 = desaturate, 2 = double saturation. |
| sat_add | FLOAT | 0.00-1–1 | Additive saturation offset applied after multiplication. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |