ComfyUI Node

xLUT

Give Your Renders a Film Grade Without Re-Rolling the Seed

By criskb·Created 7 months ago·Updated 5 months ago· 0
xLUT
  • image
  • lut_image
  • image
  • lut_info
  • lut
settings_json{"lut_name":"None","strength":1.0,"generated_lut_size":33,"generated_style_strength":1.0,"apply_generated_lut":true}

The fastest way to ruin a good render is to re-roll the seed because the colors feel off. A LUT is the deterministic answer that's been hiding in plain sight: a lookup table that maps every input color to an output color, applied in milliseconds, no sampler involved. That's what xLUT does - and it goes one step further, because it can also build a LUT from a reference image you feed it. It's part of MKRShift Nodes, a big solo-maintained pack from Cris K B that bundles look development, finishing, and output utilities.

How it works

xLUT has two personalities, and which one you get depends on how you feed it.

First: apply an existing grade. You pick a .cube LUT from the node's dropdown, and xLUT loads it and runs your image through a trilinear lookup. No model, no VRAM, just a table lookup with a strength blend. If the image has an alpha channel, it passes it through untouched - only RGB gets graded.

Second, the cleverer mode: generate a LUT from a reference image. Wire a lut_image in and xLUT builds a 3D cube (33³ by default) by computing per-channel quantile curves from the reference's histogram, then applies a saturation and midtone-tint adjustment scaled by generated_style_strength. This is statistical look-matching, not a literal grade clone - it moves your palette toward the reference's feel the way a color-match node does, but baked into a reusable LUT.

The inputs that matter

Only two required inputs, and one of them is unusual:

  • image - the frame you're grading. Feed it anything: a raw sampler output, an upscaled image, a single frame from a video batch.
  • settings_json - a multiline JSON string holding lut_name, strength, generated_lut_size, generated_style_strength, and apply_generated_lut. You rarely touch it by hand: xLUT ships a custom frontend widget, so you get a real dropdown and sliders that serialize into this field.
  • lut_image (optional) - the reference that becomes the generated LUT. Without it, xLUT just applies whatever lut_name points at.

For the generated mode, generated_lut_size (4–64) is your quality knob - 33 is the standard, 17 is fine for a quick preview - and generated_style_strength pushes the saturation/tint more aggressively. apply_generated_lut: false is a genuinely useful trapdoor: it makes the node emit the LUT without applying it, which is exactly what you want when you're building a look to save, not to grade this pass.

What comes out

  • image - the graded result.
  • lut_info - a status string. Trust it; it tells you whether the LUT applied, whether it fell back to passthrough, and why.
  • lut - the MKR_LUT payload. This is the pack's LUT currency: wire it into xLUTOutput to save it as a .cube file, or into other LUT-aware nodes.

Installing it

ComfyUI Manager → search "MKRShift Nodes", install, restart. Or the manual route:

cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes

No pip requirements, no model downloads. Restart ComfyUI and the node shows up under MKRShift Nodes → Color → LUT.

Where people get burned

The dropdown starts empty - the pack ships no LUTs. The node scans its own luts/ folder plus ComfyUI/input/luts/, so drop your .cube files there and refresh. If you get "No LUT selected", the node is passing your image through untouched; that's by design, not a bug. And if a lut_info message says a LUT "was not found," the file isn't where the scanner looks. One more expectation to set: a generated-from-image LUT gets you a similar feel, not frame-perfect color matching - use it to unify a batch, not to copy a grade exactly.

CategoryMKRShift Nodes/Color/LUT

Inputs (3)

NameTypeDefaultDescription
imageIMAGE
settings_jsonSTRING{"lut_name":"None","strength":1.0,"generated_lut_size":33,"generated_style_strength":1.0,"apply_generated_lut":true}
lut_imageoptIMAGE

Outputs (3)

NameTypeDescription
imageIMAGE
lut_infoSTRING
lutMKR_LUT