Force Aspect On Bounds
Reshape a Box to Fit an Aspect Ratio
- new_x
- new_y
- new_width
- new_height
Aspect ratio is the boss of most ComfyUI output problems. Generate at the wrong ratio and your subject comes out stretched; crop a region to the wrong shape and your composition dies. Force Aspect On Bounds is the node that takes any bounding box and reshapes it to a target aspect ratio while keeping it inside the image and, crucially, keeping whatever you care about included. It's the geometric cousin of TinyBee's Face Body Aspect Bounds - same idea, but for a general box rather than a face-inside-body problem.
How it works
The inputs split into three groups. The box you're reshaping: x, y, width, height. The canvas it must fit inside: image_width, image_height. The shape you want: aspect_ratio (width ÷ height, default 1.0) and fit_mode (maintain_height or maintain_width - which dimension stays put while the other is derived).
The optional include_* inputs are where it gets clever. If you supply include_width and include_height (and the related include_x/include_y, plus include_rel_xy to make those relative to the original box's corner), the node treats that as a region that must stay inside the result. It computes the union of your box and the include-rect, resizes to the aspect, clamps to the image, and only then shifts position as needed to keep the include-rect covered. That's the machinery for "make a crop that has this exact aspect and doesn't cut off the important bit."
Outputs are new_x, new_y, new_width, new_height - the reshaped, integer-rounded box.
The algorithm, in rough order:
- Union the original box with the include-rect (if any).
- Resize to the target aspect around the box's center, preserving whichever dimension
fit_modepicks. - Scale down if the result would overflow the image.
- Clamp inside the image; if an include-rect exists, shift (never rescale) to keep it covered.
- Round to whole pixels and re-enforce the exact aspect.
That last "re-enforce" step is doing real work: pixel rounding can drift a box off-ratio, so the node re-derives one dimension from the other after rounding, twice, falling back gracefully if the height would overflow. You get an exact-ratio box at the cost of occasionally having a dimension land one pixel under the image edge.
Where you'd actually use it
- Crop region prep: make an aspect-correct inpaint/crop box around a detected subject (pair with TinyBee's rect nodes upstream).
- Consistent output framing: force every region in a batch to the same ratio for uniform output sizes.
- Detector output cleanup: detection boxes are never cleanly proportional - this normalizes them.
Installing it
Part of ComfyUI-TinyBee under 🐝TinyBee/Util:
- ComfyUI Manager → Install Custom Nodes → search "ComfyUI-TinyBee" → Install, then restart ComfyUI.
cd ComfyUI/custom_nodes
git clone https://github.com/TinyBeeman/ComfyUI-TinyBee
Restart. No models; pure geometry. (The pack's requirements.txt lists pillow and jsonata; neither is used.)
Gotchas
The fit_mode choice matters more than it looks. maintain_height keeps your vertical size and derives width - right for a portrait crop where the face must stay in frame. maintain_width is for the opposite. Get it backwards and the node will still produce an exact-ratio box, just one that resized the dimension you wanted preserved. And if aspect_ratio is set to 0 or negative, the node skips aspect work entirely and just clamps the original box inside the image - useful to know when you're passing a ratio that might come out 0 upstream. The include-rect path is genuinely powerful, but start without it: box + ratio + fit_mode is already enough for most crops.
Inputs (13)
| Name | Type | Default | Description |
|---|---|---|---|
| x | INT | 0-10000–10000 | — |
| y | INT | 0-10000–10000 | — |
| width | INT | 5121–10000 | — |
| height | INT | 5121–10000 | — |
| image_width | INT | 5121–10000 | — |
| image_height | INT | 5121–10000 | — |
| aspect_ratio | FLOAT | 1.000.01–100 | — |
| fit_mode | COMBO | maintain_height | 2 options: maintain_height, maintain_width |
| include_xopt | INT | 00–10000 | — |
| include_yopt | INT | 00–10000 | — |
| include_widthopt | INT | 00–10000 | — |
| include_heightopt | INT | 00–10000 | — |
| include_rel_xyopt | BOOLEAN | false | — |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| new_x | INT | — |
| new_y | INT | — |
| new_width | INT | — |
| new_height | INT | — |