Exposure Adjust
Proper f-stop exposure control, not a brightness slider
- images
- IMAGE
Most "brightness" sliders you'll meet in image tools work in gamma space and give you results that don't match how light actually behaves - push them too far and things clip or go muddy in a way that doesn't look like a real camera. Exposure Adjust does it the way a camera actually does: in f-stops, in linear light. If you've ever wanted to brighten or darken a render the way you'd adjust exposure on a real photo, this is the node built for that.
Why f-stops and linear space matter here
A camera's exposure is measured in stops, where each stop is a doubling or halving of light. That's a multiplicative operation, and it only behaves correctly if you're operating on linear light values - the raw physical brightness - not on sRGB values, which have a gamma curve baked in specifically so images look right on a screen. Apply exposure math directly to sRGB pixels and you get incorrect, non-physical results, especially in the midtones and highlights. That's why this node has separate input_mode and output_mode settings: it converts into linear space, does the actual exposure math there, then converts back out.
Inputs and outputs that matter
stops(-100 to 100, default 0, step 0.01) - the actual exposure adjustment. +1 stop doubles brightness, -1 halves it, same as a camera. In practice you'll rarely go past roughly ±3 before things blow out or crush to black.input_mode/output_mode-sRGBorlinear. If your image is a normal rendered/generated image (the common case), leave both onsRGB; the node handles the round-trip through linear space internally. Set these tolinearonly if you're actually working with linear data already.tonemap-linear(no tonemapping, can clip highlights hard),Reinhard(the default - a classic HDR tonemap curve that compresses bright values instead of hard-clipping them), orlinlog.tonemap_scale(0.1–10, default 1) - how aggressively the tonemap compresses the highlight range.
Output: a single IMAGE.
Installing it
ComfyUI Manager, search ComfyUI Image Filters, or:
cd ComfyUI/custom_nodes
git clone https://github.com/spacepxl/ComfyUI-Image-Filters
Restart. No models to fetch - this is pure math on pixel values. The pack's dependency on opencv is the one thing to watch: conflicting opencv installs from other node packs cause import errors on startup. Run import_error_install.bat from the repo, or manually strip every opencv-* package and install just opencv-contrib-python.
Where people get burned
The most common mistake is leaving tonemap on Reinhard and being confused why pushing stops way up doesn't blow the image out the way you expected - that's the tonemap doing its job, compressing highlights instead of clipping them. If you actually want the raw clipped look (or you're comparing against how a plain multiply would behave), switch tonemap to linear.
The second one is mixing up input_mode/output_mode. If your source is a normal sRGB image and you accidentally set input_mode to linear, the node will treat already-gamma-corrected values as if they were linear light and the result comes out wrong - usually far too dark or blown out in a way that doesn't respond sensibly to the stops value. When exposure changes look "off" in a way plain brightness adjustment wouldn't produce, check these two settings before touching stops further.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| stops | FLOAT | 0.00-100–100 | — |
| input_mode | COMBO | 2 options: sRGB, linear | |
| output_mode | COMBO | 2 options: sRGB, linear | |
| tonemap | COMBO | Reinhard | 3 options: linear, Reinhard, linlog |
| tonemap_scale | FLOAT | 1.000.1–10 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |