Nodes/ComfyUI-DiffHDR/DiffHDR Postprocess
ComfyUI Node

DiffHDR Postprocess

The one node that undoes DiffHDR's log curve

By claussteinmassl·Created 2 days ago·Updated a day ago· 5
DiffHDR Postprocess
  • images
  • hdr

DiffHDR Postprocess takes the frames that came out of your VAE decode, which are still in DiffHDR's log-gamma encoding, and converts them back to linear scene-referred HDR. One input, one output, no widgets. It is the smallest node in this pack and, in a modular graph, the one you'll most often forget - and the symptom of forgetting it is not an error message, it's grey, low-contrast output that you'll spend twenty minutes blaming the sampler for.

Why a node is needed at all

DiffHDR doesn't sample ordinary image values. The whole pipeline works in a log-gamma space: your frames were encoded with pow(log(2.2·x + 1) / log(2.2·65536 + 1), 1/2.2) on the way in, and the model reconstructs that. It's the standard trick for high dynamic range - compressing a huge radiance range into a well-behaved 0–1 window - and it's why the model can hand you four stops of recovered highlight at all.

The VAE decodes the latent back into that same log-encoded space. So what leaves VAEDecode looks like a washed-out, milky image, because it literally isn't an image yet: it's an encoding.

Postprocess inverts it exactly: it clamps negative values to zero (VAE output drifts slightly below zero and log_to_lin needs a non-negative input), then applies (exp(x^2.2 · log(2.2·65536 + 1)) − 1) / 2.2. The 65536 ceiling is DiffHDR's headroom - the brightest thing the curve can represent is about 16 stops above 1.0, which is why the hdr output can carry a sun.

Inputs and output

  • images - VAE-decoded, log-encoded frames. That is, the direct output of VAEDecode in a DiffHDR modular graph, after the latent trim.
  • hdr - float linear Rec.709, values legitimately above 1.0.

That's the whole node. No exposure, no operator, no colour space picker, because there's nothing to decide: the curve is fixed by what the model was trained with, and any deviation would be a different, wrong answer.

From here, hdr goes to DiffHDR Save EXR for delivery, to DiffHDR Tonemap Preview for looking at, or into a relight / colour-match node. What it must not go into is anything 8-bit: SaveImage, PreviewImage, most upscalers. Those assume a gamma-coded 0–1 image, and a linear HDR frame will arrive looking dark and flat, then clip the moment you try to brighten it. This is the same scene-linear-vs-sRGB mismatch that the VFX handoff has had forever - gamma-encoded values treated as linear light blow out every blend.

Where it goes in the graph

DiffHDR Apply LoRA → ModelSamplingSD3 (shift 8)
DiffHDR Preprocess → WanVaceToVideo (control_video, control_masks)
KSampler (cfg 1) → TrimVideoLatent → VAEDecode → DiffHDR Postprocess → Save EXR / Tonemap

Copy workflows/diffhdr_modular.json from the repo rather than rebuilding it; the same file also carries the ModelSamplingSD3 shift and the cfg-1 sampler settings that the node needs to produce anything sane.

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 registers under DiffHDR. Manager users can install the pack by searching its title.

Getting it wrong

  • Using it with the all-in-one node. DiffHDR (Image / Video) and DiffHDR HDRI (Panorama) already invert the curve before handing you hdr. Run that output back through Postprocess and you've applied the inverse curve twice - highlights will detonate into four- and five-digit numbers. Postprocess is for modular graphs only.
  • Placing it before the VAE decode. It takes decoded frames. On a latent it will happily produce nonsense.
  • Judging it on an 8-bit preview. The first thing most people do is look at the hdr tensor in a preview node and conclude it's broken. It isn't; it's linear. Use DiffHDR Tonemap Preview with an exposure of −2 to −4 stops - the author's own demo images are shown at −4 EV, which is where the recovered sky and trees actually become visible.
  • Anything that isn't Wan 2.1 VAE. The curve is DiffHDR's, not the VAE's, but the pipeline around it expects wan_2.1_vae.safetensors; the check is in the all-in-one nodes, and a mismatched VAE in a hand-built graph will show up as colour weirdness or banding rather than a clean error.
  • Nodes missing from the menu after install usually means your ComfyUI predates the comfy_api V3 interface this pack registers through - it imports and registers nothing. Update ComfyUI.
CategoryDiffHDR

Inputs (1)

NameTypeDefaultDescription
imagesIMAGEVAE-decoded, log-encoded frames.

Outputs (1)

NameTypeDescription
hdrIMAGELinear HDR (Rec.709 primaries).