PD-crop by mask
Tight-crop to a mask's bounding box
- image
- mask
- image
- mask
Crop nodes in ComfyUI want numbers. You type a box, you get a box - which is great until the thing you actually want to keep isn't at fixed coordinates. PDCropByMask takes the smarter route: you hand it an image and a mask, it finds the bounding box of whatever the mask says matters, and it crops the image and mask together to fit. Padding optional.
That's the core loop behind most masked detailing, by the way - the KB's masking doc boils the whole "detailer" genre down to "zoom in on a mask, upscale, re-diffuse." This node is the zoom-in step. It also shines for normalizing sticker sheets, making a tight box for compositing, or trimming dead canvas around a subject you just cut out.
How it works
The code is short and honest. Three things happen in order:
- If the mask doesn't match the image dimensions, it's upscaled (nearest-exact, so no smoothing - keep your masks at a decent resolution).
- If you feed one mask with a batch of images, the mask is expanded to cover the batch. Mismatched batch sizes that can't be reconciled raise an error with a message telling you what's off.
- It finds every pixel where the mask is <= 0.5 (the dark region), computes that region's bounding box, applies your padding, and crops both outputs to the same box.
The one gotcha that bites everyone
The node crops to the dark part of the mask. Not the bright part. mask <= 0.5 is the rule, and that's backwards from the convention almost every other ComfyUI node uses, where white = foreground. This pack's author consistently treats black = subject (their other nodes say so in the README outright), so PDCropByMask is built for masks where the subject is dark.
Feed it a normal white-on-black mask from, say, a SAM or a segmentation node and you'll get a crop of the background instead of the subject. The fix is one core node: run your mask through InvertMask before it hits this one, or generate your mask with the subject in black. Get that right and the rest is trivial.
Inputs and outputs
image(IMAGE) - the thing to crop.mask(MASK) - decides where the crop box goes. Subject should be dark, per above.padding(INT, default 0) - the only knob. Positive values add a border of pixels around the mask's bounding box; negative values trim inside it. This is the author's own description, and it's accurate:padding=16gives you breathing room so ears and hair tips don't get shaved;padding=-8tightens in on a mask that over-covers.
Outputs are image and mask, both cropped to the exact same box - which is the whole point. Because the mask comes along, everything downstream stays aligned: you can feed the pair to an upscale-then-paste loop, an inpaint, or a compositor without re-deriving coordinates.
Troubleshooting
Two failure modes, both with decent error messages baked in. If padding removes the entire mask - say, a thin mask and padding=-50 - it throws with the minimum safe padding for that mask, which is nicer than the usual silent bad crop. And if the mask batch can't be reconciled with the image batch you get a clear Mask batch N does not match image batch M. The quieter gotcha is resolution: because mask resizing is nearest-exact, a tiny 64px mask stretched over a 1024px image gives blocky crop boundaries. Work at full resolution when you can.
Install
Pack-level, same as every node in Comfyui_PDuse. ComfyUI Manager, search "Comfyui_PDuse", or:
cd ComfyUI/custom_nodes
git clone https://github.com/7BEII/Comfyui_PDuse
cd Comfyui_PDuse
pip install -r requirements.txt
No model downloads - this is pure tensor math. It won't rival a model-based segmenter for picking what to crop, but if you already have the mask, it's the tight, deterministic way to turn it into a crop.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask | MASK | — | |
| padding | INT | 0-16384–16384 | Positive values add a border; negative values trim inside the mask boundary. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |