Save Image (Stegaflow)
The Save Node That Buries Your Workflow in the Pixels
- images
ComfyUI already stuffs your workflow JSON into the PNG's metadata - that's the whole "workflow included" culture. So why would you ever need a save node that also hides it in the actual pixels? Because people keep stripping the metadata. Re-upload an image to Discord or Imgur, re-export through some editor, and the tEXt chunk is gone; drag the file back into ComfyUI and you get nothing but a picture. Stegaflow's one and only node, Save Image (Stegaflow), is a drop-in replacement for the default Save Image that encodes the workflow into the lowest bit of every pixel's RGB channel. Strip the metadata all you like - the workflow is still in the image.
Let's be honest about what this is first: the author flat-out calls it a vibe-coded proof of concept, and the code matches (it builds a giant list of every pixel coordinate before touching anything - works, but it's not winning any awards). It's a single-node pack with a tiny footprint, and it's not something you'll find in every workflow. But the trick itself is real, it works, and for a genuinely narrow scenario - "I need my workflow to survive metadata stripping" - there isn't a lighter option.
How it works
When you queue, the node grabs the workflow from ComfyUI's hidden extra_pnginfo, prefixes it with a magic header ("ComfyUI\0"), and writes the bytes one bit at a time into the least-significant bit of the red, green, and blue channels of a clockwise spiral starting at the top-left corner and working inward. That's 3 bits per pixel - a 1024×1024 image holds roughly 384 KB of workflow, which is far more than any real workflow JSON, so capacity is rarely your problem. Visually, flipping only the lowest bit per channel is imperceptible.
On the front end, the bundled JS overrides ComfyUI's file-drop handler. Drop a PNG onto the canvas and it reads the pixels, extracts the LSBs in the same spiral, checks for the magic header, and loads the recovered workflow. That's the whole loop.
The inputs that matter
It's an output node - no outputs, nothing to wire onward. Just replace your Save Image with it and connect your images:
- images - the tensor to save.
- embed_in_pixels - the steganography toggle. On by default; this is the whole point of the node.
- embed_in_metadata - also writes the standard PNG metadata. On by default, and you should probably leave it on: it's free redundancy, and only metadata-aware tools read it.
- filename_prefix - the normal Save Image prefix, including
%date:yyyy-MM-dd%-style formatting.
Installing it
ComfyUI Manager → search "Stegaflow" and install, or:
cd ComfyUI/custom_nodes
git clone https://github.com/guill/comfyui-stegaflow
Restart ComfyUI. There's no requirements.txt to fight with - it uses numpy and Pillow, which ComfyUI already ships, and no model downloads. The catch is the API: it targets ComfyUI's newer V3 node API (comfy_api.latest), so on an older ComfyUI the node won't register at all. Update before you troubleshoot anything else.
Where people get burned
The big one: only pixels untouched since saving can be decoded. Any resize, crop, or lossy re-encode scrambles the LSBs and the drag-drop silently falls back to the original handler - no workflow, no error, just a plain image. The spiral stores data from the outer edge first, so a crop that deletes the border kills the header immediately. If you saved with embed_in_pixels on but the image was too small for the JSON, the Python side prints a "Could not encode workflow in pixels" warning and saves the metadata-only image anyway.
Also worth knowing: recovery happens in your browser on drag-and-drop only. Loading the same PNG through the gallery or a Load Image node won't pull the workflow out of the pixels - that path still relies on the normal PNG metadata. So the survival story is specifically: PNG file, pixels untouched, dragged onto the canvas.
If your output PNGs already carry their metadata fine, this node is an answer to a question you don't have. But the moment you're shipping images somewhere that eats metadata, it's the only save node that keeps the recipe in the picture.
Inputs (4)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | The images to save. | |
| filename_prefix | STRING | ComfyUI | The prefix for the file to save. This may include formatting information such as %date:yyyy-MM-dd% or %Empty Latent Image.width% to include values from nodes. |
| embed_in_pixels | BOOLEAN | true | Embed workflow data in image pixels using steganography (LSB encoding). |
| embed_in_metadata | BOOLEAN | true | Embed workflow data in PNG metadata (standard method). |
Outputs (0)
No outputs