DiffHDR Tonemap Preview
How to actually see a linear HDR frame
- hdr
- image
Every DiffHDR node in this pack hands you a float, linear, scene-referred image with values that go well past 1.0. ComfyUI's preview and save nodes do not live in that world - they expect gamma-coded sRGB in [0, 1]. Tonemap Preview is the two-line bridge between the two: it scales by an exposure in stops, applies an operator, and encodes to sRGB so you can look at the result.
Skip it and the failure isn't dramatic. The hdr tensor renders as a dark, flat image in the standard preview, which is exactly the shape of "the model didn't do anything". It did. You're looking at linear light through an sRGB assumption - the same mismatch that makes an unmanaged EXR look wrong in a compositor.
What it does
The order matters, and this is the whole node: multiply by 2^exposure in linear space, then apply the operator, then encode with the sRGB OETF. Exposure before tone mapping is what makes the node a viewer rather than a filter - you're moving along the exposure axis of the HDR data and choosing what to look at.
hdr- the linear HDR image from any DiffHDR node, or fromDiffHDR Postprocessin a modular graph.exposure- stops, −16 to +16, step 0.25, default 0. The single most useful control in the whole pack. −4 is the author's demo exposure, and it's the one that shows you whether the reconstruction was any good: at −4 the previously clipped region separates into sky and foliage instead of staying a white shape.operator-reinhard(default) compresses highlights with the per-channelx/(1+x), so a value of 20 lands somewhere sensible instead of pure white.clipignores that and just shows the 0–1 range at your chosen exposure.- Output
image- sRGB, [0, 1], ready forPreviewImage,SaveImage, or an LDR export.
clip at exposure = 0 is the before-and-after trick: it shows you exactly what an 8-bit save of the original would have looked like, with your highlights as flat white. Flip to reinhard at −4 and the difference is the thing you paid for.
What it's not for
Tonemapping is for looking and for LDR delivery. It is not the HDR deliverable. If a compositor, a game engine or a lighting artist is downstream, send them the EXR from DiffHDR Save EXR - float, with the real chromaticities in the header - not a tonemapped PNG. The community corner that cares about this is small and mostly compositors, but the rule is old: decode to linear, carry it as float, agree on the transforms. Reinhard is a nice viewer curve, not a colour-management policy.
Also worth knowing: the previews you've seen in the pack's README are tonemapped at a stated exposure. If you're chasing "why doesn't mine look like the demo", set the same exposure and operator before you change a single sampler setting.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/claussteinmassl/ComfyUI-DiffHDR.git
pip install -r ComfyUI-DiffHDR/requirements.txt # OpenEXR + huggingface_hub
Restart ComfyUI; the node lives under DiffHDR. Or install the pack from ComfyUI Manager by searching its title. You don't strictly need the OpenEXR dependency for this node, but it's in the same requirements.txt as everything else in the pack.
Gotchas
- Wiring it into an LDR graph. If the incoming image already came from
SaveImage-land - ordinary sRGB 0–1 pixels - the node will treat them as linear, multiply by2^exposureand re-encode. At exposure 0 that's a mild lift; at +4 it's mush. It only goes after a DiffHDRhdroutput. - Blaming the tonemap for a dull result. This is a viewer; if the frame looks flat at 0 EV, try −2 or −4 before you go touching
steps. Then judge the highlights at 0 EV, where clipping is the whole question. - Comparing runs across different exposures. Two renders shown at different stops will look different even when the HDR underneath is identical. The pack's own quality tables mean it: the metric that holds up across seeds is the mean log value of the reconstructed region, not the brightest pixel. Eyeballing p99.9 by eye, at a different exposure, is how people talk themselves into a worse setting.
- Previewing a batch of 99 frames. The tonemap is a couple of tensor ops per frame; it's the preview node that will try to show all of them. Save first, preview a slice.
- Nodes missing from the menu after install is nearly always an old ComfyUI: this pack registers via the
comfy_apiV3 interface and stays invisible on older builds.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| hdr | IMAGE | Linear HDR image. | |
| exposure | FLOAT | 0.00-16–16 | Exposure offset in stops. |
| operator | COMBO | reinhard | reinhard compresses highlights; clip shows the LDR range at the chosen exposure. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | sRGB image in [0,1]. |