Light Leak
Light leaks that are physics, not an orange PNG on top
- image
- image
- leak_mask
Most "light leak" effects are a translucent orange gradient PNG screen-blended over your image. They look like a gradient PNG screen-blended over your image. Darkroom's Light Leak is the version that actually reasons about what a leak is: stray light hitting the film outside the lens path, modeled as an exposure event and composited additively in linear light. It adds a constant absolute luminance to the frame, like real leaking light does - not a tint on top.
The mechanism is one equation driving both the falloff and the color, and it's the neatest thing about the node. Light entering the film edge travels laterally through the base and dye layers, which absorb short wavelengths hardest. So all three channels start equal at the entry point, and blue dies first as the light travels inward. The result: a near-white hot core at the edge that reddens as it fades toward the middle. That's why real leaks are orange - not because film is nostalgic, but because the blue got eaten. The same physics predicts the exception: a pinhole strikes the emulsion from the front with no lateral path, so it stays the neutral color of its source.
Three geometries live under leak_type:
- Sprocket trap - edge falloff modulated by the real KS-1870 perforation lattice, so the leak comes in as a comb that diffuses into a smooth wash as it spreads.
diffusionwidens and softens the teeth with depth; at 0 they keep straight sides and read as a bar chart. - Gradient - the seal, bellows or 120 backing-paper glow. A
colour_sourceswitch picks the base path (the derived white-core-to-red gradient), the honest 120 roll-paper dye tint, or a neutral source color. - Pinhole - camera-obscura spots sized by
a + D*θfrompinhole_diameter(hole size) andflange_distance(hole-to-film distance). Deeper body, bigger spot.
Inputs that matter: leak_type, leak_from (8 edges/corners; sprocket collapses a corner to its edge because perforations run along the long side), strength (the exposure added, in linear light - 0 is a passthrough), and falloff (the red channel's penetration depth in px; green and blue follow at 0.62 and 0.38 of it - that ratio is the reddening). displacement is the hidden gem: it warps the path length so the leak boundary wanders instead of running dead parallel to the frame edge, and because color follows path length, the red fringe wanders with it. A straight-edged leak is the tell that it's a filter.
Outputs. image plus a leak_mask of the leak field. Wire the mask into your compositing so the leak stays off the subject - a leak burning straight through a face is a dead giveaway. For a sequence, leave vary_per_frame off so the same leak sits on every frame; a leak that flickers between frames is worse than none.
Install. ComfyUI Manager, search "Darkroom", or:
cd ComfyUI/custom_nodes/
git clone https://github.com/jeremieLouvaert/ComfyUI-Darkroom.git
pip install -r ComfyUI-Darkroom/requirements.txt
Restart, and it's under AKURATE/Darkroom/Film. Requirements are just scipy and opensimplex - no models, no keys, no GPU needed.
One gotcha: Light Leak is a spatial node, so it's banned from the pack's LUT bake chain (neighborhood operations corrupt a 3D LUT lattice). If you're exporting a .cube of your grade, apply the leak to graded_photo after LUT Bake Extract, not inside the chain. The README lists it explicitly as not bake-safe - the pack takes its LUT pipeline seriously.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| leak_typeopt | COMBO | sprocket trap (perforation modulated) | Sprocket = edge falloff modulated by the KS-1870 perforation lattice. Gradient = seal/bellows wedge. Pinhole = camera-obscura spots, neutral by physics |
| leak_fromopt | COMBO | top | Which edge or corner the light enters from. Sprocket collapses a corner to its edge, since perforations run along the film's long edge |
| strengthopt | FLOAT | 0.450–3 | Leak exposure added, in linear light. 0 = passthrough |
| falloffopt | FLOAT | 20020–1200 | Red-channel penetration depth, ref-px @1024 long edge. Green and blue follow at 0.62 and 0.38 of it, which is what reddens the leak with distance |
| colour_sourceopt | COMBO | base path (derived red-shift) | Base path = the derived white-core-to-red gradient. Backing paper = 120 roll-paper dye, an honest preset. Neutral = source colour, no lateral path |
| diffusionopt | FLOAT | 0.350–1.5 | Sprocket only: lateral spreading of light past a perforation. Above 0 the comb widens and softens with depth; at 0 the teeth keep straight sides and read as a bar chart |
| pinhole_countopt | INT | 31–40 | Pinhole only: number of holes in the body/bellows |
| pinhole_diameteropt | FLOAT | 0.300.02–3 | Pinhole only: hole diameter in mm. Sets the penumbra (the 'a' term in spot size = a + D*theta) |
| flange_distanceopt | FLOAT | 5010–300 | Pinhole only: hole-to-film distance in mm. Spot size = a + D*theta, so a deeper body projects a larger spot |
| displacementopt | FLOAT | 1000–500 | Warps the PATH LENGTH so the leak boundary wanders instead of running parallel to the frame edge. Because colour follows path length, the red fringe warps with it. 0 = clean analytic field |
| displacement_scaleopt | FLOAT | 380142–1500 | Warp feature size, ref-px @1024. Clamped at 142 (5mm of seam): anything finer stops being a mechanical gap variation and reads as noise running through the effect |
| vary_per_frameopt | BOOLEAN | false | Batch of N gets N different leaks. Off keeps one leak across the batch, which is usually what you want for a sequence |
| seedopt | INT | 420–4294967295 | Seeds the perforation phase, the pinhole placement and the displacement warp |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| leak_mask | MASK | — |