Nodes/WAS Node Suite v3/Image Crop by Mask
ComfyUI Node Runs on cloud

Image Crop by Mask

Crop to exactly what a mask marks — and get told how to paste it back

By WASasquatch·Created 3 years ago·Updated 4 days ago· 1,844
Image Crop by Mask
  • image
  • mask
  • cropped_image
  • crop_data
  • bounds
  • cropped_mask
bbox_mode
padding0
threshold0.50
divisible_by8

The automated-fix loop that runs ComfyUI - detect a broken region, crop it, re-render it, paste it back - lives or dies on one detail: the crop and the paste have to agree about where the rectangle was. Image Crop by Mask is the node that makes that agreement explicit. It crops each image to the tightest box around whatever its mask marks, and hands you not just the crop but the window it was cut from, so a downstream Image Paste Crop can drop the fixed result back into the exact same rectangle.

It's from WAS Node Suite, WASasquatch's MIT pack (457 nodes in v3). If you've built an inpaint-and-paste region fix by hand - cropping with a math chain, praying the coordinates line up - this is the version where the bookkeeping is built in.

The inputs that matter

  • mask - decides where the crop sits. The box is measured on the mask, so the mask needs to be the same size as its image or the crop lands in the wrong place. Everything above threshold (default 0.5) counts as marked; 0.5 boxes the mask's solid core, 0.0 pulls in its whole feathered edge.
  • padding - extra pixels kept on all four sides, trimmed where the box would run off the picture. This is the one to raise for inpainting: 0 crops tight against the mask, but 32–64px of surroundings gives the re-render pass context to match against and hides the seam. Inpainting KB lore says exactly this - the padding is what makes "only masked" look seamless.
  • bbox_mode - how a batch of masks is treated. union uses one rectangle covering every mask; per_frame gives each image its own box, which is what follows a subject that moves across a sequence.
  • divisible_by - rounds both crop sides down to a multiple of this (8 suits most samplers) so the sampler doesn't silently round for you. The crop window is measured before this rounding, so Image Paste Crop still lands on the rectangle actually cut.

What comes out

Four outputs, and each one exists because someone needed it:

  • cropped_image - one crop per input image, all the same size so they travel as a single batch. That uniform size is the trick that lets one crop window describe a whole batch.
  • crop_data - the window, for Image Paste Crop to put the finished region back at its original position and size.
  • bounds - the same rectangle as rows of top/bottom/left/right, for wiring into the pack's Draw Image Bounds node to visualize what got cut.
  • cropped_mask - the mask cut to the crop's rectangle at the crop's size, so an inpainting pass knows exactly which pixels were marked.

The workflow it powers

Wire the mask (however you got it - an auto-detector, a SAM pass, a hand-paint), crop, run the region through a re-render at its native resolution, then paste via crop_data. The padding is where quality lives: too tight and the fix has nothing to blend against; too loose and you're re-rendering half the frame. Threshold trips people up too - crank it to 1.0 and no pixel counts as marked, so every frame gets cropped whole (the node names the offender in the console). A genuinely blank mask does the same.

Install and gotchas

WAS Node Suite installs via ComfyUI Manager ("WAS Node Suite v3") or git clone https://github.com/WASasquatch/was-node-suite-comfyui into ComfyUI/custom_nodes, then restart. Needs ComfyUI 0.14.0+ and Python 3.10+; v3 installs no extra Python packages, unlike the old v2 whose pinned dependencies caused famous import failures.

The two real traps: a mask whose size doesn't match its image (everything mis-crops silently), and per_frame mode's paste behavior - the paste window there is the union rectangle, so pasting stretches every crop across the whole shared box and lands exactly only where every mask shared a box. If you're per-frame cropping a moving subject and pasting each back, check whether you actually want the union window or want to paste crop-by-crop.

CategoryWAS Suite/Image/Masking

Inputs (6)

NameTypeDefaultDescription
imageIMAGEThe images to cut down. The box is measured on the mask and then sliced straight out of the image, so a mask that is not the same size as its image crops in the wrong place. A batch comes back the same length.
maskMASKMarks the area to keep. The tightest box around everything above threshold decides where the crop sits. A blank mask crops that frame whole.
bbox_modeCOMBOWhich box a batch of masks is cropped to. 'union' uses one rectangle covering every mask; 'per_frame' gives each image its own, following a subject that moves.
paddingINT00–16384Extra pixels kept on all four sides of the marked area, trimmed where the box would run off the picture. 0 crops tight against the mask; 64 leaves an inpainting pass some of the surroundings to match against.
thresholdFLOAT0.500–1How bright a mask pixel must be, from 0.0 to 1.0, to count as marked. 0.5 boxes a mask's solid core; 0.0 takes its whole feathered edge in.
divisible_byINT81–64Rounds both sides of the crop down to a multiple of this and resizes to match, which saves a sampler rounding it. 1 leaves the crop as cut.

Outputs (4)

NameTypeDescription
cropped_imageIMAGEThe cropped regions, one per input image and all one size, so they travel on as a single batch. That size is a multiple of divisible_by.
crop_dataCROP_DATAThe crop window, for Image Paste Crop to put the finished region back in the right place at its original size. In per_frame mode it holds the union rectangle, so a paste stretches every crop across that whole rectangle and lands exactly only where every mask shared a box.
boundsIMAGE_BOUNDSOne row per image giving the rectangle it was cropped from, as top, bottom, left and right pixel positions, to wire into Draw Image Bounds.
cropped_maskMASKThe mask cut to the same rectangle as the crop and carried at the crop's own size, so an inpainting pass knows which pixels were marked.