ComfyUI Node

ICO Packer

ICO Packer doesn't make an .ico — it's the tray that carries your icon frames

By wakaura-asaho·Created 6 months ago·Updated 15 days ago· 2
ICO Packer
    • ico_packer
    ◄crop_imagesfalse►
    ◄crop_reference_pointcenter►

    If you landed here hoping ICO Packer writes a .ico file: it doesn't. Not one byte. Its single output is a bundle - a plain Python dict of images and optional masks, keyed by pixel size - and it hands that bundle to the node that actually writes the file, Save Image Advanced (ICO). The pack deliberately moved the per-size sockets off the saver and onto this node, because a saver with fourteen image inputs was unusable.

    So why a middle node? Because a Windows .ico isn't one image. It's a container holding the same picture at several sizes (16, 24, 32, 48, 64, 128, 256 px), and Explorer picks whichever fits the context: 16 in the taskbar, 256 in a big thumbnail view. Packing those frames coherently is a bookkeeping job, and this is the bookkeeping node.

    How the size slots work

    There are no image sockets until you add them: right-click the node and pick Add Input (a dialog asking for one size), Batch Add Input (queue several sizes, then apply), or Remove Input (drops the last pair). Each addition creates a matched pair - an image and a mask socket for that size - labelled Image (64) / Mask (64). Sizes must be one of 16, 24, 32, 48, 64, 128, 256, and you can have at most seven pairs - seven is how many sizes that set has. Add only the ones you want; a 16/32/48/256 spread covers Windows fine.

    Masks are optional per size: wire one in and the saver uses it as the alpha channel; leave it empty and the frame keeps whatever alpha the image already has. Under the hood it walks its connected inputs, reads the size out of each socket name, crops, and returns a dict of {sizes, images, masks}. No resizing, no palette reduction, no disk I/O - all saver-side. So if your icon comes out at the wrong colour depth, the packer isn't the culprit.

    The two inputs you'll actually set

    • crop_images (off by default) - when on, frames larger than their slot get cropped down to exactly the slot size. Masks get the same crop window. Important limit: it only ever crops down. If the incoming image is smaller than the slot in either dimension, the node passes it through untouched, and the saver will reject it as size-mismatched. This is the single most common way an icon silently loses a frame.
    • crop_reference_point - center or top-left, the anchor for that crop window. The frontend greys this widget out while crop_images is off, which is a nice touch. Use center when the subject sits in the middle (the usual case), top-left when the source was already composited for exact alignment and centring would shift it.

    The output

    One socket: ico_packer, of type ICO_PACKER. That type exists only for the saver - it's a dict, not a tensor, so it can't go into a resize or preview node. Size order rides inside the bundle, so the saver writes frames ascending by size unless you tell it to sort explicitly.

    Installing

    ComfyUI Manager, search ComfyUI-Image-Process (or Install via Git URL with the repo link), then restart. Manually:

    cd ComfyUI/custom_nodes
    git clone https://github.com/wakaura-asaho/comfyui-image-process.git
    pip install -r comfyui-image-process/requirements.txt --upgrade-strategy only-if-needed
    

    Take that --upgrade-strategy only-if-needed flag; it's the author's own advice. The pack targets modern ComfyUI only - written against the V3 node schema, needs ComfyUI 0.12.3+ and a frontend 1.37.11+ - and the dynamic size slots are a frontend feature, so on an old install you get either no node or a right-click menu that does nothing. Read requirements.txt rather than the README's short dependency list: it also pulls opencv-python and scikit-image, used elsewhere in the pack, so it's a heavier install than the README implies.

    Where people get burned

    The packer never scales. The chain is: make your art, resize or crop it to each target size upstream, then pack. The bundled example workflow (workflows/example_workflow_imagesv_ico.json) wires resizing and cropping into the size slots for exactly this reason.

    Invalid frames fail late and quietly. Each slot only accepts a frame whose dimensions exactly match its label - a 512×512 image in the 256 slot is not resized for you. The saver spots the mismatch, writes that frame out as _INVALID.png, and bundles whatever's left. If your .ico opens with three sizes instead of four, go find the _INVALID.png and fix the upstream resize.

    An empty packer isn't an error until it is. Add slots, wire nothing, and the packer is happy; the saver isn't, and it throws ICO Packer has no images and stops the run. A mask wired into a slot with no image at that same size is simply ignored.

    One last reality check: almost nobody talks about producing .ico files from ComfyUI, so don't expect a thread to bail you out when this misbehaves. Read the two tooltips, keep the slot sizes honest, and it does what it says.

    CategoryWakaura

    Inputs (2)

    NameTypeDefaultDescription
    crop_imagesBOOLEANfalseWhen enabled, images (and masks) larger than the slot size are cropped to that size before packing.
    crop_reference_pointCOMBOcenterWhen Crop Images is enabled, choose the anchor for the crop window.

    Outputs (1)

    NameTypeDescription
    ico_packerICO_PACKER—