๐ Aioli Mask BBox V2
The crop node that would rather add grey bands than stretch your inpaint
- image
- mask
- image_cropped
- mask_cropped
- x
- y
- orig_width
- orig_height
- width
- height
- target_size
- image_area
Why you'd want a "bbox" node at all
Cropping the mask and stitching the result back is the one inpainting trick that survived the instruction-model era. Render a small region at native resolution and a 64-pixel eye gets 1024 pixels of generation budget, while the rest of the frame never touches the VAE. Same logic as Impact Pack's detailer loop, pointed at a mask you painted instead of a detector's box.
AioliMaskBBoxV2 is the front half of that pattern. Give it the full image and mask; it returns a crop to sample, a cropped mask, and the four numbers to put the result back. No coordinates to type.
How the geometry actually works
The rule is deliberately single, which is why it replaced two older nodes. It finds the mask's bbox, grows it by padding, grows it again to the aspect ratio of the model-side size, centres that on the bbox and drops it into the image as close as it fits. If the rectangle is bigger than your picture - a square crop on a 16:9 shot, a mask in a corner - the missing strip is flat grey rather than a squeeze. That's the personality here: it never stretches and never cuts your bbox. x / y can come out negative, and orig_width / orig_height include the bands.
resolution is not a side length. It's a pixel budget in square equivalents: 1024 means "as many pixels as 1024 ร 1024", spent at your crop's ratio. The closest multiple-pair within ยฑ5% of Nยฒ wins - a 3:2 crop at 1024/16 lands on 1248ร832, a 16:9 on 1392ร784. Nothing is more elongated than 4:1, so a thin brushstroke gets context on its short side instead of going to the model as 64ร3200. Cross 2048ยฒ (4.2 MP) and the console warns you about VRAM, which is fair.
And the cap that surprises people: a crop larger than Nยฒ is only shrunk if force_target_downscale is on. Otherwise it goes at native size, capped at 2048ยฒ - which is why resolution seems to do nothing in whole-image mode.
The inputs that matter
image and mask are obvious; the mask is resized onto the image if their definitions disagree, so a mismatch costs sharpness but not a crash.
padding- margin in pixels around the bbox, default 48. That's your main lever on "the model needs to see the neighbourhood", and it's ignored withcontext = full_image.multiple-8 (VAE minimum)/16 (Flux)/32 (SD1.5)/64 (SDXL), default 16. If the sampler complains about dimensions, you picked wrong, not the node.resolution- the pixel budget above.0means native size.force_square- square crop. Worth trying on edit models that quietly recrop non-1:1 input; the bands are what make it possible without distortion.context-regioncrops around the mask;full_imagesends the whole picture but keeps your regional mask, so the assembler still pastes back only the masked zone.
Optional band_color (default 0.5) sets that grey; leave it alone unless your model is fussy about mid-grey.
Ten outputs. image_cropped / mask_cropped go to the sampler, x / y and orig_width / orig_height wire into BBox Multiple Assembler's x / y / width / height, width / height report what the model got, target_size echoes your resolution, and image_area (1 on real pixels, 0 on bands) feeds Inpaint Color Fix's measure_area so the grey doesn't skew its colour stats.
Installing it
ComfyUI Manager โ search "Aioli Nodes" โ install, restart. Or, if you'd rather see the code:
cd ComfyUI/custom_nodes
git clone https://github.com/aiolicollective/aioli-nodes
Restart and it shows up under Aioli Nodes. Nothing to download, no model files, no dependencies in pyproject.toml - just torch, numpy and math. Rare, and worth saying: this pack can't break your environment.
Where people get burned
Do not recompose with ImageCompositeMasked. It can't handle negative x / y. The assembler resizes the crop back and copes with the off-canvas origin - it's the only supported partner.
An empty mask doesn't mean "edit everything". The bbox falls back to the whole image, the mask stays black, and you get a console warning and a no-op. Use empty_mask = full_image on Mask Split Regions upstream instead.
Whole-image crops pick up a fringe - 1โ2 px of band at ร16, up to ~15 px at ร64, dropped at recompose.
Migration paperwork. The 1.6 node is still registered as Aioli Mask BBox (legacy), hidden from search but loadable, so old workflows keep running - same nine outputs. But resolution counts pixels rather than the long side, so a saved 1024 on a 3:2 crop becomes 1248ร832, not 1024ร688. Re-check that one number when you rebuild. Also, the node's tooltips are still in French: accurate, just French.
The pack is at 1.7.1 and changes behaviour nearly every release - pin the version you validated.
Inputs (9)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | โ | |
| mask | MASK | โ | |
| padding | INT | 480โ4096 | โ |
| multiple | COMBO | 16 (Flux) | 4 options: 8 (VAE minimum), 16 (Flux), 32 (SD1.5), 64 (SDXL) |
| resolution | INT | 10240โ4096 | Taille modele en equivalent carre (N x N pixels). 0 = taille native. Un crop plus grand que N^2 n'est reduit a N^2 que si force_target_downscale est on ; sinon il garde sa taille native, plafonnee a 2048^2. |
| force_square | BOOLEAN | false | โ |
| force_target_downscale | BOOLEAN | false | On : un crop plus grand que N^2 est reduit a N^2. Off : taille native plafonnee (2048^2) โ pour l'image entiere, resolution n'a alors plus d'effet. |
| context | COMBO | region | 2 options: region, full_image |
| band_coloropt | FLOAT | 0.500โ1 | โ |
Outputs (10)
| Name | Type | Description |
|---|---|---|
| image_cropped | IMAGE | โ |
| mask_cropped | MASK | โ |
| x | INT | โ |
| y | INT | โ |
| orig_width | INT | โ |
| orig_height | INT | โ |
| width | INT | โ |
| height | INT | โ |
| target_size | INT | โ |
| image_area | MASK | โ |