Apply LUT
A film look in one node, and why a LUT beats a re-gen
- image
- lut
- image
A LUT is a table of colour in, colour out. Not a filter, not a prompt, not a model - a lookup. Feed it a pixel's RGB and it hands back a different RGB, interpolated between the eight nearest entries in a cube. That's why a grade costs about as long as a memory copy while a re-gen costs minutes, and why it gives you the same answer every single time.
Apply LUT is the applier. It takes an image batch and a LUT, and grades one with the other.
The input that isn't a filename
lut is a custom socket type of the pack's own, and that's the thing to know before you start hunting for a widget to type a path into. You don't point this node at a .cube file. You wire it a LUT from something that makes one - Load LUT in the same pack, which is where the file handling lives: its menu takes a LUT: name entry for any .cube found in a models/LUT directory (or the pack's own luts folder), a built-in look, or Custom, which builds a table from exposure, contrast, saturation, vibrance, gamma, temperature, tint and per-channel balance controls. LUT Blender mixes two tables into one. Save LUT (.cube) writes one back out. Tables stored as curves rather than a cube are converted on the way in, so you don't have to know which kind you've got.
strength does what you'd hope: 1.0 applies the look outright, 0.0 returns the pictures untouched, 0.5 halves it by mixing the graded result back over the original. Half-strength is where most strong film looks actually belong, and it saves you owning a second, subtler LUT.
use_threads and threads are for batches. Leave them off on a GPU - one pass over the whole batch is already faster - and turn them on for a long CPU-bound sequence, where 0 threads means one worker per core, up to the number of frames.
One output, image, in the same size and batch order as the input.
Why this instead of a prompt or a re-gen
The palette of an image is one of the few things a diffusion model is genuinely bad at holding still. Ask for "teal and orange" and you get teal and orange somewhere. A LUT is deterministic: every frame gets the same treatment, which is exactly the property you want across a video sequence, or a batch of product shots that have to match each other.
It's also the right move for the case where the image is fine and the look is wrong. Regenerating to fix colour throws away the composition you liked and rolls the dice on anatomy again. Grading it doesn't. Same argument as colour-matching a composited region instead of re-rendering it.
And it's the cheap end of photorealism work. The folk-standard recipe for making AI footage read as captured rather than generated is post: grain, a slight grade, vignetting, a touch of aberration. None of those need a model.
Installing it
Part of WAS Node Suite v3 (MIT, WASasquatch; 468 nodes, one of the packs that got these operations into ComfyUI in the first place):
cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui.git
ComfyUI Manager, searching WAS Node Suite v3, is the recommended install. ComfyUI 0.14.0+ and Python 3.10+. The pack installs no Python packages, downloads nothing, and never runs pip - its colour work runs on torch, on ComfyUI's own device. First start writes config.yaml and its folders under <ComfyUI user dir>/was-node-suite/, and it's a second or two slower for it.
The LUT nodes and the luts directory live in the extras feature group, which is on by default. If Apply LUT is missing from your menu, that's the switch - features.extras in config.yaml. And if you're on an old v2 install reading a tutorial that tells you to pip-install OpenCV first: don't, that's not how v3 works, and those Import Failed threads are from a pack that no longer exists in that shape.
Small traps
Grading a batch and expecting per-frame variety - you get the same grade on every frame, by design.
Heavy LUTs at full strength. A 65-point table from a hard film look can crush blacks and clip highlights irreversibly; that's what strength is for.
And the last one is a real one: a LUT applied in sRGB is a creative grade, not colour management. If you're handing frames to a compositor working in scene-linear EXR, the LUT belongs in that pipeline, not in ComfyUI's tensor space. For everything that ends up as a PNG, this node is exactly the right tool.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | The pictures to grade. The whole batch is graded at once, so a video sequence gets exactly the same treatment frame to frame. | |
| lut | LUT | The colour lookup table to apply, from Load LUT or LUT Blender. A table stored as curves rather than a cube is converted first. | |
| strength | FLOAT | 1.000–1 | How far the graded result is mixed over the original. 0.0 returns the pictures untouched, 1.0 applies the look outright, 0.5 applies it at half strength. |
| use_threads | BOOLEAN | false | Whether to grade the frames of a batch on several CPU threads at once. Leave it off on a GPU, where one pass over the whole batch is already fastest; turn it on for a long CPU-bound sequence. |
| threads | INT | 00–64 | How many worker threads to use. 0 picks one per CPU core, up to the number of frames. Ignored while use_threads is off. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | The graded pictures, same size and batch order as the input. |