Nodes/Create Ultra HDR Image/Create Ultra HDR Image
ComfyUI Node

Create Ultra HDR Image

Make your ComfyUI images actually glow on a phone — real Ultra HDR JPEGs

By overcloud81·Created 6 months ago·Updated 6 months ago· 8
Create Ultra HDR Image
  • image
  • preview_hdr
  • gain_preview
target_luminance503
highlight_strength1.0
jpeg_quality95
filename_prefixUltraHDR

Your generations look great on your monitor and flat the second they hit your phone's camera roll. That's not bad taste - it's the format. Your phone renders in HDR, and ComfyUI hands you a plain sRGB PNG. This node is one of the very few things in the ecosystem that closes that gap: it turns your SDR image into a real Ultra HDR JPEG (ISO 21496-1, the standardized version of Android 14's format) using Google's libultrahdr. No API, no key, no model download - the encoding binary ships inside the pack.

The clever part is that an Ultra HDR JPEG is still a normal JPEG. Devices that don't know gain maps show the plain SDR picture; devices that do (Android 14+, iOS 18, Windows 11, Chromium) apply the embedded gain map and render highlights beyond the display's normal range. The README brags that "even GPT-4o can't output Ultra HDR," which is a weird flex - no text API outputs gain maps - but the underlying claim holds: this is genuinely the only ComfyUI node doing this right now.

How it works

Under the hood it's a three-stage pipeline:

  1. Tone mapping. The SDR image is linearized, converted to Rec.709 luminance, and treated as ~100-nit content. The author's algorithm leaves darks alone, lifts mids with a gentle power curve, and climbs the top end toward your target luminance with local-contrast boosting.
  2. Gain map. The HDR/SDR luminance ratio becomes a single-channel grayscale gain map clamped between 1.0 and target/100 - single-channel, which avoids the color casts multi-channel gain maps get.
  3. Encode. It writes the untouched SDR image as a JPEG, builds a 10-bit YUV420 sidecar, and shells out to the bundled ultrahdr_app (libultrahdr) binary to merge them into the final file.

Grounding honesty: this is display-space HDR, not captured HDR. It expands highlights that are already in your image - it won't conjure detail out of a clipped sky. Finishing node, not a fixer.

The inputs that matter

One image in, four knobs - three you'll actually touch:

  • image - an sRGB IMAGE tensor from anywhere in your graph. Heads up: it processes only the first frame of a batch.
  • target_luminance (203–1000, default 503) - peak brightness in nits. 203 is the spec minimum; 503 approximates a decent HDR phone screen. The main quality lever: higher means more dramatic highlight separation, but more risk of pushing past what your source supports.
  • highlight_strength (0.8–2.0, default 1.0) - how aggressively highlights get expanded. Crank it for punch, back off if the high end turns artificial.
  • jpeg_quality (50–100, default 95) - quality of the SDR base JPEG; a low base quality degrades the HDR view too. Leave it at 95.
  • filename_prefix - output name, auto-incremented so nothing is overwritten. Slashes make subfolders: HDR/test/UltraHDR.

The outputs

Two IMAGE outputs, both meant for PreviewImage nodes. preview_hdr is the SDR image with a "Peak: XXX nits" text overlay - a quick way to confirm the mapping did something. gain_preview is the grayscale gain map (normalized 0–1), a debugging view: white is where the brightest expansion happens, gray means "unchanged." The actual Ultra HDR file saves straight to ComfyUI/output/ as prefix_00001.jpg; grab it there, not from the previews.

Install

ComfyUI Manager (search "Create Ultra HDR" or "ComfyUI-Create-UltraHDR"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/overcloud81/ComfyUI-Create-UltraHDR.git
pip install scipy

Restart, and it shows up under image/HDR. The UI is bilingual and switches to Chinese if your system locale says so. Only real dependency beyond numpy/Pillow is scipy, plus the bundled ultrahdr_app binary - no heavy DL deps, no model downloads.

Gotchas and troubleshooting

  • macOS is the gap. Binaries ship for Linux and Windows only (bin/linux, bin/windows). The code checks for bin/macos then PATH, but no macOS binary is in the repo, so on a Mac you get "ultrahdr_app not found" unless you compile libultrahdr's ultrahdr_app yourself and put it on PATH. The same error on Windows or Linux means the binary path is broken - re-clone.
  • "I can't see any HDR." Then your display or viewer doesn't support it - on an SDR monitor the file is just the JPEG you started with, by design. Test on a phone, Chrome, or Windows 11's Photos app.
  • The workflow isn't in the file. It saves JPEG, which has no room for ComfyUI's embedded workflow chunks. Keep your master PNG; this is a derivative for sharing, not your archive.
  • License check: BSL-1.1: free for personal use, but commercial embedding needs a license from the author (auto-converts to Apache 2.0 in 2030). For a hobbyist, never comes up.

If you want your renders to look right on the thing most people actually view them on, this is the only game in town.

Categoryimage/HDR

Inputs (5)

NameTypeDefaultDescription
imageIMAGE
target_luminanceINT503203–1000
highlight_strengthFLOAT1.00.8–2
jpeg_qualityINT9550–100
filename_prefixSTRINGUltraHDR

Outputs (2)

NameTypeDescription
preview_hdrIMAGE
gain_previewIMAGE