Nodes/Vintage Effect/Vintage Effect
ComfyUI Node

Vintage Effect

Make AI photos look shot, not rendered — vintage grain, JPG rot, and all

By brucew4yn3rp·Created 10 months ago·Updated 8 months ago· 3
Vintage Effect
  • images
  • IMAGE
quality70
passes1
grain_strength5
vignette_strength0
color_gradeFaded
color_grade_strength50
saturation70
blur_typeNone
blur_strength0

Your Flux/SDXL output looks wrong in a way you can't name. Skin is too even. Colors are too punchy. Edges are too crisp. It's too perfect - nobody's camera takes a picture like that, so your brain quietly files it under "rendered." The Vintage Effect node is the fix: one image-in/image-out node that bakes in exactly the imperfections real photos have - film grain, faded color, darkened corners, and yes, actual JPG compression artifacts.

This is the same advice the photorealism crowd keeps landing on, packaged as a single node: grain and noise in post make images read as captured rather than generated, and AI images are chronically oversaturated and over-contrasty, so pulling saturation down and adding a color cast helps more than any "ultra realistic" prompt token. Vintage Effect bundles all of it so you don't have to assemble grain, vignette, and grading from three separate packs.

How it works

Under the hood it converts your batch to PIL, then runs a fixed pipeline: color grade → saturation → grain → blur → vignette → JPG re-encode. The standout trick is the last step. It saves each image to a JPEG in memory and reopens it, once per passes value. Re-encoding lossy files over and over is what produces that soft, blocky, "uploaded to Facebook in 2009" degradation that noise alone can't fake. Nothing else in the pack calls an API or needs a key - it's pure CPU numpy/Pillow, torch in and torch out.

The inputs that matter

Only one input is required in the strict sense (images), but you'll touch these:

  • quality (default 70) - JPG quality, 0–100. Lower means more artifacts. Note 0 is silently clamped to 1 in the code, so "0" isn't full destruction; the real range is 1–100.
  • passes (default 1) - how many times it re-encodes. More passes = more degradation. This is the "generation loss" dial.
  • grain_strength (default 5, 0 disables) - film grain. Values read high: the code divides your number by 2, so 100 is aggressively noisy. Start around 5–15.
  • color_grade (default Faded) with color_grade_strength (default 50) - None/Warm/Cool/Faded/Sepia. Faded drops contrast to 0.75 and lifts brightness; Sepia is a classic matrix. Strength blends the grade back toward the original, so 50 is a gentle wash.
  • saturation (default 70) - 100 is original, below that you go toward gray. The default already pulls you down 30%, which lines up with the "AI is oversaturated, desaturate in post" playbook.
  • vignette_strength (default 0) and the blur trio (blur_type + blur_strength) - both off by default. Vignette is a quadratic darkening toward the corners; blur offers Gaussian, Box, motion/radial/lens/soft-focus, all good for the dreamy-lens look.

The single output is an IMAGE, so it drops straight into your VAE decode → Save Image chain, or upstream of an upscaler if you want to bake the look before sharpening.

Installing

Install via ComfyUI Manager (search "Vintage Effect"), or:

cd ComfyUI/custom_nodes
git clone https://github.com/brucew4yn3rp/ComfyUI_VintageEffect

Then restart ComfyUI. It pulls in torch, Pillow, numpy, and scipy - scipy is only actually imported when you use the motion-blur types, so you'll likely already have everything in your venv. No model files, no downloads, no keys.

Where people get burned

The node quantizes everything through uint8 PIL and drops alpha on RGBA images (JPEG has no transparency), so don't feed it images you need transparency from. And because it's all CPU numpy, a big batch at low quality with multiple passes is slow - it's a finishing step, run it once on the image you actually keep, not on every preview. If you need a live preview, keep grain low; at high settings each frame's noise is random, so the grain shimmers between previews.

It's a niche node with a small footprint, but for one specific job - convincing film-look finishing on a photo-real workflow - it does in one node what usually takes three.

Categoryimage/effects

Inputs (10)

NameTypeDefaultDescription
imagesIMAGEThe images to apply vintage effect to.
qualityINT700–100JPG compression quality. Lower = more artifacts (0-100)
passesINT11–10Number of compression passes. More passes = more degradation
grain_strengthINT50–100Amount of film grain. Set to 0 to disable (0-100)
vignette_strengthINT00–100Vignette darkness around edges. Set to 0 to disable (0-100)
color_gradeCOMBOFadedColor grading preset
color_grade_strengthINT500–100Strength of color grade effect. 0 = disabled, 100 = full effect (0-100)
saturationINT700–200Color saturation (0 = grayscale, 100 = original, 200 = max boost)
blur_typeCOMBONoneType of blur to apply
blur_strengthINT00–100Strength of blur effect. Set to 0 to disable (0-100)

Outputs (1)

NameTypeDescription
IMAGEIMAGE