ComfyUI Extension: ComfyUI_Gear
Run ComfyUI workflows without the setup
No installs, no CUDA version roulette, no GPU sitting idle on your bill. Bring a workflow and run it in the browser.
VFX-oriented nodes for ComfyUI: HDR LogC3 / LogC4 decode, EXR I/O, and an interactive ACEScct color grading panel powered by exr-viewer.
Looking for a different extension?
Custom Nodes (6)
README
ComfyUI_Gear
VFX-oriented custom nodes for ComfyUI.
Currently ships:
- Gear · LogC3 Decode + Save EXR — inverse-LogC3 a
[0,1]LoRA output to scene-linear HDR and write a float16 EXR. Ceiling ~55 linear (≈8.3 stops above mid-gray). - Gear · LogC4 Decode + Save EXR — same idea with ARRI LogC4. Ceiling ~470 linear (≈11.3 stops above mid-gray) — ~3 extra stops of highlight headroom for HDR LoRAs trained on LogC4 targets (e.g. the V10 /
*_logc4_*family). - Gear · ACEScct Decode + Save EXR — same idea with ACEScct (AMPAS S-2016-001). Ceiling ~222.86 linear (≈10.3 stops above mid-gray) with a bounded shadow toe, so more of
[0,1]goes to shadows/midtones than LogC4. For HDR LoRAs trained on ACEScct targets (the ACEScct Prodigy r128 family). Output is 16-bit half-float EXR, ~14-bit effective (VAE-decoded). - Gear · Load EXR (linear) — read a linear HDR EXR (single file or glob for sequences) into an IMAGE batch, values unclamped (>1.0 preserved).
- Gear · ACEScct Encode — the forward curve: linear HDR → ACEScct
[0,1], with input-space handling (linear_acescgpass-through,linear_rec709→ AP1 matrix,srgb_display→ EOTF + matrix) and a pre-encode EV shift. Pair with Load EXR to feed HDR content into ACEScct pipelines (HDR-to-HDR conditioning). - Gear · Color Grade (exr-viewer) — full ACEScct grading panel (color wheels, lift/gamma/gain/offset, scopes, A|B compare, batch scrubber, AgX / ACES Fitted / Hable / Reinhard tone mappers, .cube LUTs) embedded as a modal pop-up powered by exr-viewer.
More nodes will be added over time. The pack is structured so adding one is editing one file (see Layout below).
Install
Via ComfyUI Manager
Search for ComfyUI_Gear and install. Restart ComfyUI.
Manual
cd ComfyUI/custom_nodes
git clone https://github.com/oumad/ComfyUI_Gear
cd ComfyUI_Gear
pip install -r requirements.txt
Then restart ComfyUI. The grade panel needs no extra setup — the exr-viewer build is committed in web/vendor/.
Usage
LogC3 / LogC4 / ACEScct Decode + Save EXR
Three sibling nodes with identical I/O — pick the one that matches the curve your LoRA was trained on:
| Node | When to use | Linear ceiling |
|---|---|---|
| Gear · LogC3 Decode + Save EXR | LoRAs trained on LogC3 targets (LumiVid V9, V5b, klein_step*, the LTX-2 HDR IC-LoRA, etc.) | ~55 linear (≈8.3 stops above 0.18) |
| Gear · LogC4 Decode + Save EXR | LoRAs trained on LogC4 targets (V10 / *_logc4_* family) | ~470 linear (≈11.3 stops above 0.18) |
| Gear · ACEScct Decode + Save EXR | LoRAs trained on ACEScct targets (the ACEScct Prodigy r128 family) | ~222.86 linear (≈10.3 stops above 0.18) |
Picking the wrong decode curve will silently produce wrong linear values — the EXR will look plausibly tonemapped but the absolute luminance will be off. Check your LoRA's name / docs.
Connect your HDR LoRA's [0,1] log-compressed output (an IMAGE) to image. Outputs:
hdr_linear— scene-linear HDR tensor (values can exceed 1.0). Pipe into Gear Color Grade or anyIMAGE-consuming node.tonemapped_preview— quick Reinhard preview atpreview_evfor the graph UI.exr_paths— newline-joined absolute paths of saved EXRs.
The filename_prefix accepts ComfyUI tokens (%year%, %month%, %day%, %hour%, %minute%, %second%, %batch_num%). EXRs are auto-counter-suffixed so they never overwrite.
Color Grade (exr-viewer)
Wire hdr_linear to the grade node, run the graph once. Click Open grade panel on the node — the modal pops up with the exr-viewer interface.
- Live preview: every slider, color wheel, and master moves the WebGL canvas instantly. No graph re-run needed.
- Persistence: changes are ephemeral until Save (blue, ✓). Cancel / × / Esc / click-outside discards. Saved state survives modal reopen and workflow save/load — including the exact dot+master position on each color wheel.
- A|B compare: connect an
IMAGEto the optionalsdr_referenceinput, clickA|Bin the panel toolbar, and drag the wipe line. Works across batches — scrubbing the timeline swaps both EXR and SDR. - Batches: pass an
[N, H, W, C]IMAGE; the panel shows a frame scrubber at the bottom. - .cube LUTs: click
LUTin the toolbar to load any.cubefile (1D LUTs not supported). Bundled film LUTs live inweb/vendor/exr-viewer/test-luts/.
Outputs:
graded_display— display-referred sRGB (post tone-map + OETF), 0..1.graded_linear— scene-linear HDR after grading, pre-tonemap. Pipe back into a Gear LogC3 Decode's EXR writer (or any saver) to bake the grade into your EXRs.
The grade math runs in two places that stay in sync:
exr-viewer/src/renderer.ts— GLSL fragment shader (drives the live preview).gear/grading.py— torch port (runs on backend execution).
Section headers match 1:1, so a change in one is a mechanical mirror in the other.
Layout
ComfyUI_Gear/
├── __init__.py # registers nodes + WEB_DIRECTORY
├── pyproject.toml # project + ComfyUI Registry metadata
├── requirements.txt
├── nodes/ # one file per node (thin wrappers)
│ ├── __init__.py # aggregates NODE_CLASS_MAPPINGS
│ ├── logc3_decode.py
│ ├── logc4_decode.py
│ ├── acescct_decode.py
│ ├── acescct_encode.py
│ ├── load_exr.py
│ └── color_grade.py
├── gear/ # pure-Python library (no ComfyUI deps)
│ ├── logc3.py # ARRI LogC3 encode/decode (EI 800)
│ ├── logc4.py # ARRI LogC4 encode/decode
│ ├── acescct.py # ACEScct (AMPAS S-2016-001) encode/decode
│ ├── aces_mats.py # Rec.709<->AP1 matrices + sRGB EOTF (no OCIO)
│ ├── grading.py # torch port of renderer.ts
│ └── exr_io.py # float16 EXR writer
├── web/ # ComfyUI frontend extension
│ ├── gear_grade.js # button → modal → postMessage bridge
│ └── vendor/ # synced from exr-viewer/dist/ (committed)
│ ├── exr-viewer/ # SPA loaded by the iframe
│ └── lib/ # standalone renderer bundle (reserved)
└── scripts/
└── sync_from_exr_viewer.py # contributor tool: refresh web/vendor/
Adding a new node
- Create
nodes/my_node.pywith a class exposingINPUT_TYPES,RETURN_TYPES,FUNCTION,CATEGORY, and aNODE_CLASS_MAPPINGS/NODE_DISPLAY_NAME_MAPPINGSpair. - If the math is reusable, put it in
gear/(no ComfyUI imports). - Import the mappings in
nodes/__init__.pyand merge them into the aggregated dicts.
That's it — __init__.py re-exports automatically.
Updating the grade pipeline (contributors)
# inside the exr-viewer repo
npm run build # rebuild the SPA → exr-viewer/dist/
npm run build:all # also rebuild the library bundle → exr-viewer/dist-lib/
# inside this repo
python scripts/sync_from_exr_viewer.py # mirrors dist/ + dist-lib/ into web/vendor/
The sync script accepts a path argument or EXR_VIEWER_PATH env var; default points at the maintainer's local clone.
End users never run npm — the prebuilt exr-viewer output is committed in web/vendor/.
Compatibility
- ComfyUI: any recent version (2024+) with the standard frontend.
- Python: 3.10+.
- GPU: any device that runs ComfyUI; the grade panel uses WebGL2 in the browser.
- OS: Windows, Linux, macOS — the embedded exr-viewer is pure browser code.
License
MIT — see LICENSE.
Credits
- exr-viewer — the GPU grading pipeline this pack embeds.
- exrs — Rust/WASM EXR codec used by the panel.
- ARRI LogC3 EI 800 and LogC4 transfer function references.
Run ComfyUI workflows without the setup
No installs, no CUDA version roulette, no GPU sitting idle on your bill. Bring a workflow and run it in the browser.