Nodes/DJZ-Nodes/Classic Film Effect
ComfyUI Node

Classic Film Effect

Nine Analog Looks in One Node

By MushroomFleet·Created 2 years ago·Updated 5 months ago· 78
Classic Film Effect
  • images
  • IMAGE
film_stockportra400
grain_intensity0.04
vignette_strength0.10
scratch_probability0.02
dust_density0.001
halation_strength0.05
enable_jittertrue
seed0

Classic Film Effect is the node for when a clean AI image is too clean. It takes your batch and pushes it through a simulated film pipeline: a film stock profile, grain, vignette, scratches, dust, and halation - everything that makes a digital image look like it was shot on actual emulsion. You pick the film from a dropdown and it handles the color science for you, which is the part people usually get wrong doing this by hand.

The film stock list is the headline feature and it's genuinely thoughtful. Nine real stocks, each with a personality: kodachrome64 (that saturated Kodak slide look), trix400 and hp5plus (true black-and-white films - the node drops saturation to zero), portra400 (the warm portrait film everyone's trying to fake), velvia50 (oversaturated Fuji slide), delta3200 (grainy high-ISO push), cinestill800t (that tungsten-balanced halation look from neon night shots). Each one sets a color temperature, contrast, saturation, highlight/shadow rolloff, and grain size. Pick cinestill800t and you're most of the way to a Blade Runner still.

How it works

The implementation is a chain of classic image-processing steps, all seeded so you get reproducible results: a color-temperature shift (warm or cool depending on the stock), film grain (Gaussian noise scaled by grain_intensity), a radial vignette, vertical scratches whose width scales with the image, Gaussian-falloff dust particles, halation, and an optional frame jitter for video. The seed input controls all the randomness, so the same seed gives you the same grain pattern - important if you're batch-processing frames and want consistent texture rather than per-frame snow.

The inputs that matter

  • film_stock - the dropdown of nine stocks. This is the whole game; change it and the entire look changes.
  • grain_intensity (0–1, default 0.04) - keep it low. 0.04 is subtle; 0.2 starts eating detail.
  • scratch_probability (default 0.02) and dust_density (default 0.001) - the damage controls. Scratch probability is a per-width count, so it scales with image size; dust density is per-pixel, so it also scales. Watch these on big images.
  • enable_jitter - on by default, adds per-frame position jitter for a handheld-film feel. Turn it off for stills.

Output is an IMAGE batch at the same resolution. Slap it after a VAE decode and before a save/video node.

Installing it

It's a DJZ-Nodes member, so:

cd ComfyUI/custom_nodes
git clone https://github.com/MushroomFleet/DJZ-Nodes
cd DJZ-Nodes
pip install -r requirements.txt

Restart ComfyUI (or install via Manager, search "DJZ-Nodes"). Needs OpenCV, nothing exotic - no model downloads.

Common issues

The biggest trap is overdoing the physical damage. scratch_probability and dust_density default to tiny values for a reason - dust_density multiplies width×height, so on a 2K image a value of 0.01 means tens of thousands of dust specks. Start at the defaults and raise slowly. Second, this is a simulation, not a lookup table: a "film stock" here is a small set of constants, so portra400 won't match a real Portra scan exactly - it just gets you the family resemblance. And because the grain is seeded, remember that changing seed changes the texture; keep it fixed across a batch if you want coherent grain from frame to frame.

Categoryimage/effects

Inputs (9)

NameTypeDefaultDescription
imagesIMAGE
film_stockCOMBOportra4009 options: kodachrome64, trix400, portra400, velvia50, hp5plus, ektachrome100, +3
grain_intensityFLOAT0.040–1
vignette_strengthFLOAT0.100–1
scratch_probabilityFLOAT0.020–1
dust_densityFLOAT0.0010–0.1
halation_strengthFLOAT0.050–1
enable_jitterBOOLEANtrue
seedINT00–2147483647

Outputs (1)

NameTypeDescription
IMAGEIMAGE