ComfyUI Node

Visual Image Crop

Crop by dragging a box, not by guessing coordinates

By Pitpe12·Created 3 months ago·Updated 2 months ago· 1
Visual Image Crop
    • uncropped_out
    • cropped_out
    • crop_metadata
    • crop_metadata_json
    • x
    • y
    • width
    • height
    image
    x0
    y0
    width1
    height1
    aspect_lockfalse
    aspect_ratiofree

    ComfyUI's built-in Crop node is fine until you have to decide that the box goes at x=137, y=92. Visual Image Crop fixes the part nobody likes: you drag a rectangle right inside the node, and the x/y/width/height widgets update themselves. It's a small, single-purpose node, and for the one job it does, it does it well.

    Read the gotcha first, because it changes how you'll use this. The image doesn't come in through a tensor input. There's no IMAGE socket waiting for your Load Image node - the image input is the node's own picker, and you load/upload/drag/paste/ctrl-V an image straight into it. That's deliberate: the README says the picker keeps the preview and the processed result identical, since a linked tensor can't be previewed before the graph runs. The trade-off is that this is a manual pre-processing tool, not a mid-graph crop. You use it to produce a crop you've eyeballed, then wire the result downstream.

    Mechanically it's simple under the hood. The web extension (web/image_crop_gui.js) draws an overlay rectangle on the node's preview with corner and edge handles, and every drag writes back to the saved x, y, width, height widgets. The Python side is just a tensor slice - source[:, y:y+h, x:x+w, :] - with a IS_CHANGED that hashes both the image bytes and the widget values, so the graph re-executes the moment you nudge the box. Width and height clamp to a minimum of 1 pixel, so you can't zero-out a crop.

    The inputs you actually touch:

    • x, y, width, height - the saved widgets. Because they're real widgets, the crop persists in your workflow JSON, and you can type exact numbers if you need pixel-perfect values.
    • aspect_lock + aspect_ratio - flip the lock on and pick from 1:1, 4:3, 3:4, 3:2, 2:3, 16:9, 9:16, 21:9. Height follows width (or vice versa when you hit an edge) so your box stays on ratio. Handy when you're pre-cropping for a model that likes a specific aspect.

    Outputs worth knowing: cropped_out is the one you wire to anything that takes an IMAGE. uncropped_out is a handy passthrough of the source - route it somewhere else and you've saved a Load Image. The four INT outputs (x, y, width, height) feed into anything that wants crop coordinates, and crop_metadata_json gives you a plain string of {"x":…, "width":…} you can stash in text or log. The crop_metadata output is a custom CROP_METADATA type that nothing else in this pack consumes, so treat the JSON string as the practical one. Also: the same rectangle applies to every frame if you load a multi-frame image, which is nice for GIFs.

    Install is painless because there's nothing to install besides the code - no requirements file, no model downloads, no API key. Either search "ComfyUI-Visual-Image-Crop" in ComfyUI Manager, or:

    cd ComfyUI/custom_nodes
    git clone https://github.com/Pitpe12/ComfyUI-Visual-Image-Crop.git
    

    Then restart ComfyUI and grab it under image/crop -> Visual Image Crop.

    Where people get burned: feeding it a tensor (it won't accept one - use the picker), or assuming the crop coordinates carry over to a differently-sized version of the image. They don't; they're in the picker image's pixel space. If you crop here and then upscale and crop again later, recompute the box. It's a young, one-commit repo from a hobbyist author, so don't expect updates - but for "let me just frame this face properly," it's exactly the tool you'd reach for.

    Categoryimage/crop

    Inputs (7)

    NameTypeDefaultDescription
    imageCOMBO1 options: example.png
    xINT00–65535
    yINT00–65535
    widthINT11–65535
    heightINT11–65535
    aspect_lockBOOLEANfalse
    aspect_ratioCOMBOfree9 options: free, 1:1, 4:3, 3:4, 3:2, 2:3, +3

    Outputs (8)

    NameTypeDescription
    uncropped_outIMAGE
    cropped_outIMAGE
    crop_metadataCROP_METADATA
    crop_metadata_jsonSTRING
    xINT
    yINT
    widthINT
    heightINT