Nodes/ComfyUI-BCNodes/PostFx Apply
ComfyUI Node

PostFx Apply

The film stock and the grain, applied after the sampler

By 0xBeycan·Created 23 days ago·Updated 3 days ago· 2
PostFx Apply
  • image
  • look
  • mask
  • image
◄themesignature/01_portra_400►
◄conditionneutral►
◄strength1.00►
◄seed0►
◄batch_seedfixed►

The single cheapest move for making an AI image stop looking like an AI image is grain. "Film grain" pulls 233 mentions in the KB's corpus, and the recipe from a thread about why AI video looks fake was post-production, not a better model: motion blur, and "a subtle grain". PostFx is the deterministic version of that, plus the film stock you were prompting for.

What it is

A film-emulation look applied to an image batch, from the postfx package: film stocks, cinematic grades and .cube LUTs, defined in YAML. Pick a theme, dial a shooting condition and a global strength, and every image in the batch wears the same reusable visual identity.

Three knobs, and they're cleanly separated:

  • theme - the look itself. 35 options including none. Three texture-only grain finishes (fine per-pixel grain, colour untouched - the default social-still finish), fifteen signature film stocks and industry grades (signature/01_portra_400, gold_200, pro_400h, ektar_100, cinestill_800t, superia_xtra, kodachrome_64, tri_x_400…), and fifteen experimental.
  • condition - neutral, day_outdoor, overcast, indoor_evening, neon_night, night_flash. It scales only the texture - grain, chroma noise, halation - and leaves colour alone. You're telling it what the camera was doing, and it responds in grain and halation rather than in grade.
  • strength - 0 to 1.5, blending the whole effect with the original. 0 is the original, 1 is the look, above 1 is over the top on purpose.

seed makes grain deterministic, and batch_seed = increment gives each frame of a batch its own grain - which matters the moment you're looking at a sequence rather than a still.

How it works

The look is a full theme dictionary - colour, grain, lens behaviour - and it runs on the CPU, per frame. That's the trade for it being deterministic and cheap on VRAM: no model load, no GPU memory, and the same input always gives the same output at the same seed.

Two optional inputs change the shape of the node. A connected look (from a PostFx Theme, Custom Look or LUT node) overrides the theme dropdown entirely - the theme widget silently stops mattering. And an optional mask limits the effect to the masked region, blending with the original outside it. One quirk to remember: an all-black mask is ignored, and the effect applies everywhere. That's deliberate, because LoadImage emits an all-zero placeholder mask for images without alpha, and nobody wants a workflow where wiring the wrong mask turns the node into a no-op.

theme = none with nothing connected to look passes the image through untouched, so you can leave the node parked in a workflow and switch it on later.

Why apply it here rather than prompt it

You can ask for this in the prompt. Naming a physical camera and stock is the highest-leverage realism trick in the KB - "Point-and-shoot film camera" beats every combination of realistic/candid/amateur - and Kodak Portra 400, Ilford HP5 and Cinestill 800T are named for exactly the effects (warm skin, honest grain, night halation) that this node's signature themes emulate.

Two reasons to do it after the sampler instead:

  1. The prompt affects the whole generation. Asking for heavy grain can cost you detail - the model blurs and adds noise, and you get a mushy image with speckle over it. Post-processing adds the grain at full sharpness.
  2. It's a look you can reuse. Same theme, condition and strength across a set is a house style. Prompting for it is a hope.

Put it last in the chain. If you're using the same pack's Skin Texture, the order it documents is Skin Texture → upscale → grain, because texture and grain are for the published still, while the clean image is what you feed an I2V pass.

Installing it

The PostFx nodes need the postfx package from requirements.txt:

cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt

With ComfyUI Manager, install ComfyUI-BCNodes and let it handle the requirements. Without postfx the pack still loads and only the PostFx nodes are missing - the import is deliberately deferred. Restart and reload the tab; they sit under BCNodes/postfx.

Where people get burned

Wiring a look and then wondering why the theme dropdown does nothing. A connected look wins, always.

Assuming the mask worked. An all-black mask means "apply everywhere", not "apply nowhere".

Strength is a blend, not a volume knob for one effect. It scales the whole look. If you want more grain specifically, add a grain theme or step up to a Custom Look rather than pushing strength past 1 and washing out the colour.

It's CPU work. Fine for a still, noticeable on a 100-frame batch - the last time I did that I made coffee.

CategoryBCNodes/postfx

Inputs (8)

NameTypeDefaultDescription
imageIMAGE—
themeCOMBOsignature/01_portra_400Built-in look. 'none' passes the image through untouched. Ignored when a 'look' input is connected.
conditionCOMBOneutralShooting condition: scales grain/chroma/halation only.
strengthFLOAT1.000–1.50 = original, 1 = full look, >1 = over.
seedINT00–4294967295Grain seed (deterministic).
batch_seedCOMBOfixedincrement = a different grain per frame across the batch.
lookoptPOSTFX_LOOKA look from a PostFx Theme / Custom Look / LUT node. Overrides 'theme'.
maskoptMASKApply the effect only where the mask is white; blend with original. An all-black mask (e.g. LoadImage on an image without alpha) is ignored and the effect applies everywhere.

Outputs (1)

NameTypeDescription
imageIMAGE—