Create Ultra HDR Image
Make your ComfyUI images actually glow on a phone — real Ultra HDR JPEGs
- image
- preview_hdr
- gain_preview
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:
- 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.
- 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. - 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 sRGBIMAGEtensor 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 forbin/macosthen PATH, but no macOS binary is in the repo, so on a Mac you get "ultrahdr_app not found" unless you compile libultrahdr'sultrahdr_appyourself 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.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| target_luminance | INT | 503203–1000 | — |
| highlight_strength | FLOAT | 1.00.8–2 | — |
| jpeg_quality | INT | 9550–100 | — |
| filename_prefix | STRING | UltraHDR | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| preview_hdr | IMAGE | — |
| gain_preview | IMAGE | — |