ComfyUI Node

C2C ACES Tonemap

The filmic tone-mapping node that makes overbright AI output look like a graded frame instead of a blown-out mess

By Code2Collapse·Created 6 months ago·Updated a day ago· 52
C2C ACES Tonemap
  • image
  • IMAGE
source_spacesRGB
exposure1.00
contrast1.00
saturation1.00
output_colorspacesRGB (gamma)

Diffusion models love to clip. Highlights slam into pure white, shadows crush to black, and the result looks fine on a phone and terrible in a real grade. ACES tonemapping is the film-industry fix: a curve that rolls off highlights instead of clipping them, so overbright pixels come back with color and smooth falloff instead of a wall of white. C2CACESTonemap wraps that in a single node with exposure, contrast, and saturation controls - the "make it look like a frame" button.

If you've ever tried to composite AI output into a VFX pipeline, you already know the deeper problem this sits next to: ComfyUI hands you 8-bit-ish sRGB tensors in a 0–1 range, while a real pipeline works in scene-linear float (the KB's post-processing doc walks through exactly that mismatch). This node is the bridge - linearize, tone map, and hand back something display-ready.

How it works

The implementation (in nodes/hdr_color_science.py) is a clean-room version of the standard ACES filmic curve - the Stephen Hill approximation you'll find in Unity and Unreal. In order: it linearizes from your chosen source space (sRGB or ARRI Log C3; "Linear" passes through), applies an exposure multiplier, does contrast around mid-gray 0.18 in log space, adjusts saturation along a Rec.709 luma axis, then runs the ACES filmic curve and encodes to your output space. It's pure PyTorch tensor math - no models, no VRAM, no dependencies.

The inputs

  • source_space - what the input is encoded as: sRGB, Linear, or Log C3. Get this wrong and everything is wrong, so be honest about what you're feeding it.
  • exposure (1.0) - multiplier before tonemapping; up to 10× if you're rescuing a dark pass.
  • contrast (1.0) - log-space contrast, 0.5–2.0.
  • saturation (1.0) - below 1 desaturates, above 1 boosts.
  • output_colorspace - sRGB (gamma) for display, Linear if you're compositing further, or ACES AP1 if you're handing off to a real ACES-managed comp.

Output is a single IMAGE.

Installing it

Part of the Code2Collapse/ComfyUI-CustomNodePacks umbrella pack. ComfyUI Manager → search "CustomNodePacks", or:

cd ComfyUI/custom_nodes
git clone https://github.com/Code2Collapse/ComfyUI-CustomNodePacks.git

Restart ComfyUI. No extra dependencies for this node. (The pack's requirements.txt has opencv-python and scipy for its other nodes; install only what you're actually missing rather than a blanket pip install -r requirements.txt over ComfyUI's bundled torch/numpy.)

Gotchas

The classic mistake is feeding it an already-gamma-encoded image while telling it the source is linear - you'll get washed-out, milky output and blame the node. Match source_space to reality. For typical ComfyUI output, sRGB-in → sRGB-out with exposure around 1.0 and the default contrast/saturation is a huge upgrade over raw output on overbright scenes; keep it there until you know why you're deviating. If you're chaining this before other color work, output Linear and do the sRGB encode last, or you'll double-gamma everything. It's a small node with a big, easy win - put it at the end of a Wan or Flux pipeline and A/B it once.

CategoryMEC/Color Science

Inputs (6)

NameTypeDefaultDescription
imageIMAGE
source_spaceCOMBOsRGBInput color space. The image is linearised from this space before ACES processing.
exposureFLOAT1.000.01–10Exposure multiplier applied before tone mapping.
contrastFLOAT1.000.5–2Contrast adjustment (applied in log space).
saturationFLOAT1.000–2Color saturation. <1 desaturates, >1 boosts.
output_colorspaceCOMBOsRGB (gamma)Output color space. sRGB for display, Linear for compositing.

Outputs (1)

NameTypeDescription
IMAGEIMAGE