LumaFlux SDR to HDR
8 Steps, No Prompt, No Strength Knob
- model
- image
- hdr_pq
- preview
HDR output stopped being a novelty in 2026. Lightricks shipped an HDR IC-LoRA for LTX in April that upgrades SDR footage to float EXR, and single-image SDR→HDR LoRAs for Qwen showed up in May. LumaFlux is the research-paper version of the same idea, and this node is where it lives in ComfyUI: feed it an IMAGE batch of ordinary 8-bit BT.709 frames, get back a PQ / BT.2020 signal mastered at 1000 nits.
The part that surprises people is what it doesn't want. No prompt, no text encoder, no CFG. No strength or denoise slider either - the reference pipeline actively raises an error if you pass one, because it always runs the full training-matched transport from t=1 to t=0.
How it works
FLUX.1-dev never generates anything here. The frozen VAE encodes your SDR frame into a latent, the pipeline adds a small bridge noise (0.05, the value from the paper's config) on top of it, and then integrates a rectified flow from t=1 down to t=0 in 8 Euler steps. What steers those steps is the adapter set you loaded: gated low-rank attention residuals driven by luminance, gradient, saturation and spectral-band cues, plus FiLM conditioning from the frozen SigLIP features. The decoded latent then goes through a monotone rational-quadratic spline - the "RQS tone decoder" - which is what actually converts the decode into display-referred HDR luminance. tone_strength is your handle on that last stage.
The video trick is equally low-key. Every frame of the batch is treated as one sequence: the first frame's noise realization gets reused for the rest, and the tone-curve parameters are smoothed frame to frame with an EMA. The paper measures a 53.3% reduction in excess flicker from those two moves, with no temporal layers, no optical flow, and no video fine-tuning.
Inputs and outputs
Four inputs are worth your attention; the rest are set-and-forget.
image is your SDR frames in [0, 1], and the semantics matter: a batch is treated as one video sequence. Ten images from a batch generator wired in here share one noise realization and get their tone curves averaged with each other. For stills, either pass one frame at a time or set rqs_ema to 0.
steps defaults to 8; the tooltip is blunt that going higher only costs time. Leave it.
rqs_ema (default 0.8) is the tone-curve smoothing weight and it is the main flicker dial. Ignored for a single image. tone_strength (0–2, default 1.0) scales the learned tone expansion: 1.0 is the paper, 0 leaves the VAE decode untouched, and going above 1 gets more aggressive expansion than the model was trained for. That's your taste knob, and the honest answer is that 1.0 is usually right.
seed seeds the bridge noise. It's only 5% of the latent, so the seed nudges details rather than rewriting a frame - but the same seed reproduces exactly.
Two outputs. hdr_pq is the PQ / BT.2020 signal in [0, 1] mastered at 1000 nits, and it goes to the save nodes or the preview node - not to the stock Save Image node, which quantizes to 8 bits and drops the color tagging, leaving you a flat gray rectangle. preview is a tone-mapped SDR view for Preview Image, using the default 203-nit Reinhard curve. It ignores any white point you'd have chosen; if you want to tune that, use the LumaFlux HDR Preview node instead.
Install
cd ComfyUI/custom_nodes
git clone https://github.com/shreshthsaini/LumaFlux
pip install -r LumaFlux/requirements.txt
Restart, or install the same thing via ComfyUI Manager (search "LumaFlux"). The adapters download to models/lumaflux/ on first use (~285 MB), FLUX.1-dev transformer and VAE come either from the gated Hugging Face repo or from the flux1-dev.safetensors / ae.safetensors files you probably already have, and SigLIP (~1.7 GB) fills the HF cache once. Then wire Loader → SDR to HDR → save nodes.
Where people get burned
Any resolution is fine. The node pads frames up to a multiple of 16 by edge replication and crops back afterwards, so you never think about it.
Speed is not why you'd use this on video. Expect ~5 seconds and 27 GB of GPU memory per 1080p frame in bf16, with a progress bar per frame: it's a serial per-frame loop, and a 30-second 24 fps clip is 720 forward passes.
Flicker with shared_noise off, or with rqs_ema at 0, is expected, not a bug - you've just disabled both stabilisation mechanisms the paper reports on.
Don't feed it something that's already HDR. Input frames are assumed to be 8-bit SDR (BT.709) in [0, 1]. Feed a PQ-encoded file back through the graph and the VAE encode gets a signal it was never trained on; you'll get a strange, over-stretched result rather than an error. Round-trip through the HDR Preview node or an 8-bit export first.
Memory is the real gate. The backbone alone takes ~24 GB, and the Loader evicts everything else in ComfyUI first. Plan for this to be the only thing running.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| model | LUMAFLUX_MODEL | — | |
| image | IMAGE | 8-bit SDR (BT.709) frames in [0, 1]. A batch is treated as one video sequence. | |
| steps | INT | 81–64 | Euler steps from t=1 to t=0. The paper uses 8; more costs time without improving quality. |
| seed | INT | 00–18446744073709550000 | — |
| shared_noise | BOOLEAN | true | Reuse one bridge-noise realization for every frame of the batch (video stabilization, on in the paper). |
| rqs_ema | FLOAT | 0.800–0.99 | Weight of the previous frame's tone-curve parameters (video stabilization, 0.8 in the paper). Ignored for a single image. |
| tone_strength | FLOAT | 1.000–2 | Scales the learned tone expansion. 1.0 is the paper; 0 leaves the VAE decode untouched. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| hdr_pq | IMAGE | PQ / BT.2020 signal in [0, 1], mastered at 1000 nits. Save it with the LumaFlux HDR save nodes; a regular Save Image node would quantize it to 8 bits and drop the HDR tagging. |
| preview | IMAGE | SDR tone-mapped view of the HDR result, for Preview Image. |