Nodes/ComfyUI_Image_Pin/Image PinNode (Embed image b64 to workflow)
ComfyUI Node

Image PinNode (Embed image b64 to workflow)

Pin an Image Into Your Workflow JSON (Yes, the Whole Image)

By CheNing233·Created about a year ago·Updated about a year ago· 5
Image PinNode (Embed image b64 to workflow)
    • IMAGE
    image
    image_data

    You know the drill: someone shares a workflow, you drag it in, and every Load Image node is empty because the PNG lives in their ComfyUI/input folder, not in the JSON. The Image PinNode from CheNing233's one-node pack exists to kill that pain - it bakes the image itself into the workflow file as a base64 string. Share one JSON, the picture travels with it.

    ComfyUI's whole sharing culture runs on the promise that a workflow is portable: the graph gets embedded into output PNG metadata, and dragging an image back reconstructs everything. That promise quietly breaks the moment a workflow depends on an input image, because the built-in Load Image only reads files from your local input directory. ImagePin patches that hole. It's a niche tool, but when you need it, nothing in core ComfyUI does it.

    How it works

    The heavy lifting is a chunk of frontend JavaScript. When you feed the node an image, the JS draws it onto a canvas, converts it to a data:image/png;base64,... data URL, and stuffs that string into a hidden image_data widget. Save the workflow and the string rides along in the JSON; open the workflow elsewhere and it's still there.

    On the Python side, load_image decodes the base64, opens it with PIL, runs exif_transpose (so phone photos stop landing sideways), converts to RGB, and hands you a normal IMAGE tensor. There's a stack-trace trick in the JS that swaps the giant string out for a [IMAGE DATA] placeholder during some UI calls so the frontend doesn't choke - you don't need to care about it, just know the real data survives export.

    The inputs that matter

    Only two, and one of them you'll never touch:

    • image - a dropdown listing every file in your ComfyUI/input folder, plus a special #DECODE_FROM_BASE64 entry. Pick a file to pin it. Once the base64 is embedded, this input is basically decorative - the Python code ignores it and always decodes image_data.
    • image_data - the hidden base64 string. Leave it alone.

    The node's one output is a standard IMAGE, so it slots anywhere a Load Image would: straight into a VAE Encode, a ControlNet preprocessor, an IPAdapter reference, whatever.

    There's also a 👉 Compress (Recommended!) 👈 button on the node. It downscales anything over 512px to a max of 512px and re-encodes as WebP at 60% quality, which shrinks the embedded string dramatically. Use it unless you genuinely need the full-res pixels embedded.

    Installing it

    ComfyUI Manager is the easy route - search "ComfyUI_Image_Pin" and install. Or do it by hand:

    cd ComfyUI/custom_nodes
    git clone https://github.com/CheNing233/ComfyUI_Image_Pin
    

    Then restart ComfyUI. There's no requirements.txt, no models to download, no API key - the whole pack is one Python file and one JS file that lean on torch/PIL/NumPy ComfyUI already ships. Find it in the node menu under utils, or just search "Image PinNode". The code is partly adapted from ltdrdata's ComfyUI-Inspire-Pack - the same Dr. Lt. Data who wrote ComfyUI Manager - so the lineage is solid even if this author is new to you.

    Where people get burned

    The tradeoff is size. Base64 inflates binary by about 33%, and that string isn't only in your JSON - if you save the output PNG, ComfyUI embeds the whole workflow (embedded image included) into its metadata. Pin a couple of 4K PNGs and your workflow file and your outputs both balloon. That's the whole reason the Compress button exists; on anything over 512px, hit it.

    The other footgun is validation. If image_data is missing or empty, the node fails with image_data is required - which is what happens if you hand-edit the JSON or grab a workflow that was saved mid-edit. Don't strip the string out. And note the dropdown wants the source file present at pin time; after it's embedded, the original file can go - the string is the source of truth.

    Worth a look if you share workflows that need reference images, want to hand an artist a gallery of prompt+image pairs, or just like your JSON to carry everything.

    Categoryutils

    Inputs (2)

    NameTypeDefaultDescription
    imageCOMBO2 options: example.png, #DECODE_FROM_BASE64
    image_dataSTRING

    Outputs (1)

    NameTypeDescription
    IMAGEIMAGE