Nodes/radiance/Tonemap
ComfyUI Node

Tonemap

Nine presets that overwrite each other, and how to actually drive it

By FXTD-Studios·Created 8 months ago·Updated about 18 hours ago· 246
Tonemap
  • image
  • image
◄preset◎ Cinematic Film►
◄operatorfilmic_aces►
◄exposure0.0►
◄gamma2.2►
◄white_point1.0►
◄contrast1.00►
◄saturation1.00►
◄highlight_compression0.50►
◄shadow_lift0.00►
◄use_gputrue►

Somewhere in every HDR workflow there's a moment where you need a displayable picture. Tone mapping is that moment: compress a scene-linear range that might span 15 stops into something a monitor can show, without the highlights clipping into flat white or the midtones going grey.

Radiance's Tonemap wraps eight curve operators and nine look presets in one node, with GPU acceleration. It's the node that turns your EXR into something you can post.

How it works, including the trap

The operators are the usual suspects, and the tooltips describe them accurately:

  • filmic_aces (default) - the industry film curve. Contrasty, familiar, good on almost anything.
  • filmic_uncharted2 - the game-industry favourite; similar family, slightly different shoulder.
  • agx - the modern Blender default. Handles saturated highlights better than the filmics: colours roll off instead of collapsing into white.
  • reinhard, reinhard_extended, reinhard_luminance - the classics. Least "look", most preserve-y of colour, flattest of result.
  • linear_clamp and exposure_only - no curve at all, and useful mostly for diagnosing what an upstream node did.

Then the ordering, which is where this node differs from a naive chain: contrast and saturation are applied before the gamma encode, so the midpoint means the same thing it does in linear. Gamma comes last, and for agx the gamma step is skipped because agx carries its own display transform. That's the correct order and it's worth knowing it's the correct order, because packs that get it wrong produce colour shifts that look like a broken operator rather than a broken pipeline.

Now the trap. The preset overrides every setting below it. preset defaults to ◎ Cinematic Film, so you can spend a happy ten minutes moving exposure and contrast and watching nothing happen. If you want manual control, set preset to None (Custom) first, then dial in the parameters. That is the single most common way people get confused by this node.

Inputs and outputs

image is required. Everything else is optional, and one of them you'll actually set: preset, then hand over to exposure (stops, -5 to +5), gamma (display gamma, 2.2 = sRGB), white_point (the brightness that maps to white - raise it for more highlight headroom), contrast and saturation around their 1.0 midpoints, plus highlight_compression (default 0.5) and shadow_lift (default 0). use_gpu defaults on and falls back gracefully.

One output: image, display-ready SDR. From here, a Preview, a Save, or a Write node. Don't feed it back into another HDR node - you've just thrown the range away, and that's the point of the node, but people do it by accident.

Installing Radiance

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

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

Windows portable users: run that pip line with python_embeded\python.exe. No model downloads for this node - it's pure maths. The pack itself (GPL-3.0, ~147 visible nodes by FXTD Studios) installs OpenEXR, OpenImageIO, OpenColorIO, diffusers and accelerate into ComfyUI's environment.

Troubleshooting

Controls do nothing. Set preset to None (Custom). Yes, really, this is the answer most of the time.

Saturated highlights go white. Try agx. That's specifically what it's better at than the filmic curves.

Result looks flat after grading it further downstream. Tone mapping is a display transform, not a creative one. If you know you're grading afterwards, grade the linear image and apply the tonemap at the end of the chain rather than the start.

A general word of caution on this pack. When Radiance was posted to r/StableDiffusion the launch thread's top comment (a fair, specific criticism) pointed out that some node implementations in the pack collapsed data to 8-bit precision while the marketing claimed a 32-bit pipeline. It's been a moving target since - 3.5.0 is a much more careful release, with honest labelling of what's a heuristic and what's learned - but if you're doing a shot you care about, verify the round trip rather than trusting a feature list. Radiance even ships nodes that exist for exactly that: a diagnostics node and Linear Check to confirm what your data actually is at each step.

Preview looks blown out on the way in. That's the SDR preview pipeline doing its job badly on HDR data, not this node failing. Use Radiance's Viewer for review.

CategoryFXTD STUDIOS/Radiance/HDR

Inputs (11)

NameTypeDefaultDescription
imageIMAGEInput HDR or SDR image to tone map
presetoptCOMBO◎ Cinematic FilmQuick look preset. Overrides settings below.
operatoroptCOMBOfilmic_acesTone mapping algorithm: • filmic_aces: Industry-standard film curve • filmic_uncharted2: Game industry favorite • agx: Modern Blender default • reinhard: Classic, preserves color • linear_clamp: Simple clip
exposureoptFLOAT0.0-5–5Exposure adjustment in stops. Negative = darker, Positive = brighter.
gammaoptFLOAT2.21–3Display gamma. 2.2 = sRGB standard. Higher = darker midtones.
white_pointoptFLOAT1.00.5–10Maximum brightness that maps to white. Higher = more headroom for highlights.
contrastoptFLOAT1.000.5–2Contrast adjustment around midpoint. >1 = more punch.
saturationoptFLOAT1.000–2Color saturation. 0 = grayscale, 1 = original, >1 = vivid.
highlight_compressionoptFLOAT0.500–1Compress highlights to prevent clipping. 0 = no compression, 1 = full.
shadow_liftoptFLOAT0.000–0.2Lift shadows to reveal detail. 0 = no lift, 0.1 = subtle.
use_gpuoptBOOLEANtrueUse GPU acceleration when available.

Outputs (1)

NameTypeDescription
imageIMAGETone-mapped SDR image ready for display or export.