RGBA Safe Pre (Swwan)
The reason your transparent PNGs don't end up with ugly fringes
- image
- mask
- image_out
- alpha
- has_alpha
The name is doing real work: this node makes transparent images safe to push through ComfyUI's RGB-only IMAGE plumbing. You know the failure - you cut out a subject, run it through any ordinary image node, and suddenly the edges are ringed with white, black, or grey fringes that weren't there before. RGBA_Safe_Pre is the first half of the fix (the "Pre"), and it exists because ComfyUI's image tensor fundamentally ignores alpha.
Why the fringes happen
Load a PNG with transparency in ComfyUI and you get two things: an IMAGE tensor with the RGB, and a MASK. Here's the catch that trips everyone up: the mask is inverted - it stores 1 - alpha, not alpha. And the RGB in the transparent regions isn't transparent at all; it's whatever color was behind the subject when the PNG was made (often black).
So when you feed that RGB into a node that blurs, resizes, or composites, the "invisible" pixels still participate with their backdrop color. That's your white/black/grey halo. The standard fix is premultiplied alpha: multiply the RGB by alpha first, so fully transparent pixels become pure black and stop contaminating their neighbors. RGBA_Safe_Pre does exactly that, and hands you the real alpha as a bonus.
How it works
The node is a front-end you put right after Load Image (or any image + mask pair). Mechanically, from the source:
- It inverts the mask back into true alpha (
alpha = 1 - mask). - It premultiplies:
image_out = image * alpha. - It works out whether the source actually had transparency, and returns that as a boolean.
If your source has no alpha at all (a JPEG, say), it doesn't do anything clever - it degrades to a clean passthrough and reports has_alpha = False. No resize, no division, no dimension changes.
Inputs and outputs
Only two inputs, and you just wire Load Image into both:
image(IMAGE) - the RGB fromLoad Imageor any image node.mask(MASK) - the maskLoad Imagegives you (remember: internally1 - alpha).
Outputs:
image_out(IMAGE) - the premultiplied RGB, ready for RGB-only nodes.alpha(MASK) - the true alpha, in[0, 1].has_alpha(BOOLEAN) - whether the source really contained transparency. Keep this connected; the companion nodes use it.
You then run the premultiplied image_out through whatever you wanted, and finish with the pack's RGBA_Safe_Post (to unpremultiply) or RGBA_Save / RGBA_Multi_Save to write a real transparent file.
Install
It's in the ComfyUI_Swwan pack. In ComfyUI Manager, search "ComfyUI_Swwan", or:
cd ComfyUI/custom_nodes
git clone https://github.com/aining2022/ComfyUI_Swwan
cd ComfyUI_Swwan
pip install -r requirements.txt
Restart ComfyUI, look under Swwan/RGBA. No models, no keys.
The traps
First, has_alpha matters more than it looks. ComfyUI emits a placeholder 64×64 all-zero mask for images with no alpha, so a JPEG still shows a mask output - this node detects that fallback and treats it as "no alpha," which is what keeps it from doing pointless math. If you're checking with a JPG and wondering why nothing changed, that's working as intended.
Second, don't use the raw alpha downstream after something changed the image size - the mask is original-resolution. That's what the Post node is for.
Third, this node only prepares. If you save straight from here without going through RGBA_Safe_Post, you'll write a PNG whose RGB is still premultiplied and it'll look too dark at the edges. The pipeline order is the whole point: Pre → process → Post/Save.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | Input RGB image from Load Image or any IMAGE node. | |
| mask | MASK | MASK from Load Image. ComfyUI stores alpha as 1 - alpha in this mask. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image_out | IMAGE | — |
| alpha | MASK | — |
| has_alpha | BOOLEAN | — |