Bleach Bypass
Bleach bypass in ComfyUI
- image
- image
You know that look - the washed-out, crushed, desaturated grade from Saving Private Ryan or 300. That's bleach bypass, a film-developing trick where the silver isn't fully removed from the emulsion, leaving highlights blown, shadows lifted, and colors stripped back. It's the shortcut to "gritty war photo" that generations of colorists have reached for, and this node gives you the whole thing as one box that takes an image and gives you an image.
Why reach for it here? Photorealism write-ups keep circling the same tells - too-smooth skin, flat lighting, AI "beauty filter" glow - and one of the fastest fixes is to stop fighting the render and just grade it. A proper bleach bypass hides a lot of sins: it eats the plastic highlight rolloff, adds punch to midtones, and makes a clean Flux or SDXL render read as "shot on film" instead of "generated." It won't add pores, but it will stop people asking if you used a filter. No LUTs, no Photoshop, no model downloads. That's the entire pitch.
How it works
The math is refreshingly honest. The source does three things: desaturate a copy of the image with PIL's ImageEnhance.Color, push the result through a normalized tanh S-curve (slope and offset are your contrast and pivot), then overlay-blend that graded base with a more saturated copy of the original. The overlay blend is the classic screen-style 2ab below 0.5, 1 - 2(1-a)(1-b) above - same trick Photoshop uses for its overlay mode.
What that means in practice: you're not just turning down saturation. You're compressing the tonal range through an S-curve and blending a colored layer back on top, which is why the result keeps a hint of color while still looking desaturated. That's the "silver retention" signature, not a cheap saturation slider.
The inputs that matter
The sweet spots are right in the tooltips, and they're worth trusting:
- slope (default 4) - how steep the S-curve is. 2–10 gives you good results; past that it gets crunchy fast.
- shadow_offset (default 0.5) - the pivot. Above 0.5 pushes shadows darker, below lifts them. Overexposed image? Nudge it up.
- desaturation (default 0.8) - how much color gets pulled out of the base layer. It never fully strips color, by design.
- overlay_strength (default 0.9) - how hard the effect lands. Keep it 0.8–1.0; lower just makes the whole thing timid.
Output is a single image, so it slots anywhere in the post-VAE chain - straight out of the decoder, before Save Image, or feeding an upscaler. The node even draws a live SVG preview of your S-curve that redraws as you drag slope and offset. It's small, but it's the best thing in this pack: you can see the curve bend before you queue.
Installing it
ComfyUI Manager is the way - search "M3D" and grab M3D photo effects. Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/metal3d/ComfyUI_M3D_photo_effects
Then restart ComfyUI. That's the whole install: there are no extra requirements. The pack only uses numpy and Pillow, which ComfyUI already ships, so there's nothing to pip-install and no models to download. This is close to the ideal tiny custom node in a ecosystem that usually means dependency roulette.
Gotchas
The author's honest about his setup: he develops on Linux and says Windows/macOS should work but isn't verified. The curve preview is marked "highly experimental" in the README and occasionally draws imperfectly - cosmetic, not fatal.
The real trap: this node handles one image at a time. The code squeezes off the batch dimension and runs the whole thing through PIL, so feeding it a batched tensor (say, a multi-frame video pass) will crash or misbehave. Process single frames. And given the pack is a two-node hobby project from an indie dev (same author behind the Templated Mask nodes), don't expect a roadmap - it does one thing, and it does it cleanly.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| slope | FLOAT | 4.01–50 | The slope of the S-curve. keep value from 2 to 10 to expect good results. |
| shadow_offset | FLOAT | 0.500–1 | The shadow offset of the image. keep value near 0.5. If >0.5 the shadows are more present, <0.5 the lights are more present. |
| desaturation | FLOAT | 0.800–1 | The input desaturation (1-value) of the image. keep value near 0.7 to 0.9 for common effect. |
| overlay_strength | FLOAT | 0.900–1 | The strength of the overlay effect. keep value near 0.8 to 1.0 for common effect. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |