Nodes/Comfy-FilmSimulator/HDR Merge (Gainmap)
ComfyUI Node

HDR Merge (Gainmap)

Stitch your SDR preview and linear HDR into one coherent image

By zhuyanan·Created 9 months ago·Updated 3 months ago· 1
HDR Merge (Gainmap)
  • sdr_image
  • hdr_image
  • merged_hdr
  • gainmap_vis
  • info
blur_radius51
max_gain8.0
mix1.00

Comfy-FilmSimulator's film node gives you two views of the same grade: a linear hdr_image with real highlight headroom, and a tonemapped preview_sdr that actually looks right on a normal screen. This node is the bridge between them. It computes a gain map - the same trick behind Google's Ultra HDR files - that describes, per region, how much brighter the HDR version is than the SDR version, smooths it so it doesn't look like a layer of noise, and uses it to rebuild an HDR image that starts from the good-looking SDR base. Then you feed the result to Save AVIF/HEIC HDR. The README calls this step optional, and it is: you can save hdr_image straight. But the merged output is usually the better file, because its base is the grade as you actually saw it.

How it works. The node takes both images (they're expected linear; if sizes differ it resizes HDR to match SDR), computes luminance for each, and forms log_gain = log(hdr) − log(sdr) per pixel. That raw ratio is a mess of noise and edge artifacts, so it Gaussian-blurs the log gain with blur_radius, exponentiates back to a gain map, clamps it to [1/max_gain, max_gain], and multiplies the SDR by the (optionally mixed) gain. Small details: the kernel is forced odd, and the blur falls back to a median blur if Gaussian chokes. The merge's ideas are credited to the Hdr-Gainmap and AlcedoStudio projects in the README, but the implementation here is its own.

The inputs that matter. Three knobs plus the two images:

  • blur_radius (default 51, odd, up to 401) - how smooth the gain map is. Bigger = fewer halos around bright objects but less local accuracy. 51 is a good photographic default.
  • max_gain (default 8) - the clamp on highlight expansion. Gain 1–8 means highlights can be up to 8× brighter than the SDR base. Lower it if merged results look crunchy.
  • mix (default 1) - how much of the computed gain actually gets applied. 0 = SDR unchanged, 1 = full HDR reconstruction.

What comes out. Three outputs. merged_hdr is the reconstructed linear HDR - wire it to Save AVIF/HEIC HDR. gainmap_vis is a grayscale picture of the gain map, normalized 0–1, which is genuinely useful for debugging why a merge looks wrong: if it's a flat gray slab, your SDR and HDR inputs don't actually correspond. info is a string reporting the gain range and effective blur - cheap to wire into a text node and worth glancing at.

One thing the README gets wrong, so you don't chase it. The README says guided filtering (edge-aware, via OpenCV's ximgproc.guidedFilter) is the default smoothing. It isn't - not in this node. The shipped hdr_merge.py uses plain Gaussian blur. Guided filtering only exists in the one-click Film Pipeline node, and only if you've separately installed opencv-contrib-python. Don't install it for this node alone; you'll get nothing for it.

Install. Same pack, same story: ComfyUI Manager → search "Comfy-FilmSimulator", or git clone https://github.com/zhuyanan/Comfy-FilmSimulator into ComfyUI/custom_nodes, restart. It needs numpy and OpenCV, which ComfyUI ships with anyway. No models, no extra downloads.

Where people get burned. Feeding it two images that aren't the same scene - e.g. an SDR preview and an HDR image from different runs - produces a nonsense gain map, and the flat-gray gainmap_vis is how you'll know. Also, remember this node expects linear inputs on both ports; if your SDR side is already gamma-encoded, disable the gamma conversion upstream (or check apply_srgb_gamma behavior in the save node) so the ratio isn't systematically wrong.

CategorySmartHDR

Inputs (5)

NameTypeDefaultDescription
sdr_imageIMAGE
hdr_imageIMAGE
blur_radiusINT511–401
max_gainFLOAT8.01–64
mixFLOAT1.000–1

Outputs (3)

NameTypeDescription
merged_hdrIMAGE
gainmap_visIMAGE
infoSTRING