Nodes/ComfyUI vsLinx Nodes/Fit Image into BBox Mask
ComfyUI Node

Fit Image into BBox Mask

Put an image exactly where the mask says — pose compositing without the guesswork

By vslinx·Created about a year ago·Updated 26 days ago· 25
Fit Image into BBox Mask
  • source
  • mask
  • destination
  • composite
  • fitted_source
  • placed_mask
  • x
  • y
  • w
  • h
modefit
align_xcenter
align_ycenter
offset_x0
offset_y0
threshold0.50
pad0
use_source_alphafalse
antialiaslanczos
canvas_w1024
canvas_h1024

Let's say you've got a pose image, a logo, a decal, or a product shot you need to drop into a scene - and it has to land in a specific region, scaled to fit, without you eyeballing the resize. This node is that whole job in one box: it reads a mask, finds the smallest rectangle that covers its white pixels, resizes your source image to fit inside that box while keeping the aspect ratio, and pastes it onto a destination image (or a fresh canvas). Out comes the composited result, plus the fitted image and mask on their own, so you can feed them anywhere.

The author's stated intent is inpainting: fit the image into the masked area, pre-process it, then run a ControlNet on that region. It's the "exact placement" half of the old masked-inpainting recipe - and even in 2026, when whole-frame edit models do most of the work, exact placement is still the one thing masks own outright.

How it works

The mechanism is refreshingly simple, all PIL math:

  1. The mask is thresholded - any pixel at or above threshold (default 0.5) counts as "set" - and the bounding box is computed from those pixels.
  2. That box is expanded outward by pad pixels, clamped to the canvas.
  3. The source is resized to fit inside the box (fit, no crop) or cover it (fill, cropping edges as needed).
  4. Alignment and pixel offset_x/offset_y place it, and it's pasted onto the destination.
  5. The placed_mask output is the intersection of the mask and the footprint rectangle - i.e. "exactly where the image actually landed."

The mask is resampled with nearest-neighbor to the destination's size if they don't match, so a small mask still works on a big canvas.

Inputs and outputs that matter

Two required inputs drive everything: source (the image you're inserting) and mask (its white area defines the box). The rest are polish:

  • mode - fit scales inside the box with no crop (default); fill covers it completely and crops the overflow.
  • align_x / align_y - where the fitted image sits in the box when the aspect ratios don't match. Center is the sane default; the edge options matter when a mask box is much wider than your decal.
  • threshold - mask brightness cutoff for box detection. 0.5 works for crisp masks; drop it for soft or faint ones.
  • pad - grows the box outward by N pixels, handy for giving your insert breathing room.
  • use_source_alpha - if on, transparent areas of the source are respected during the paste. Leave it off for fully opaque images.
  • destination (optional) - what you're compositing onto. Omit it and you get a blank canvas_w × canvas_h canvas (default 1024×1024).
  • antialias - lanczos (default), bicubic, or bilinear resampling.

Outputs: composite (destination + fitted source), fitted_source (the resized image on a black canvas - wire this into a ControlNet preprocessor or an inpaint pass), placed_mask (the exact placed region), and x, y, w, h (the box coordinates/dimensions, if you want them for other math). It's batch-aware: feed N sources and it returns N composites.

Installing

No dependencies, no model files - the pack is pure Python on top of ComfyUI's existing PIL/torch.

  • ComfyUI Manager: search "ComfyUI vsLinx Nodes", install, restart.
  • Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/vslinx/ComfyUI-vslinx-nodes.git comfyui-vslinx-nodes

Restart, and it's under vsLinx/inpaint.

Gotchas

  • An empty or black mask is a silent no-op. If no pixel crosses the threshold, the bounding box doesn't exist, and the node passes your destination through unchanged with a black fitted image and an empty mask. No error - you just get "nothing happened." If that's what you're seeing, your mask has no white in it, or your threshold is too high for a faint mask.
  • fill crops. Great when you need to cover the box edge-to-edge, but parts of your source will be cut. If the source's edges matter (a logo, a face), stay on fit.
  • Sections of the mask with feathered edges can shrink or shift the detected box. The threshold applies per-pixel, so a heavily feathered mask measures differently than the shape you think you painted. Raise pad to compensate.

It's a small node, but it's the difference between compositing by hand with three separate nodes and doing it in one. For decal, pose, and product-shot workflows, it earns its place.

CategoryvsLinx/inpaint

Inputs (14)

NameTypeDefaultDescription
sourceIMAGEThe image you want to insert (e.g. pose, object, decal).
maskMASKDefines where the image will be placed. The white area determines the bounding box.
modeCOMBOfitfit scales the image inside the mask’s box (no crop). fill covers the box completely (may crop edges).
align_xCOMBOcenterAlignment on the x axis of the fitted image inside the box if the aspect ratio doesn’t match perfectly.
align_yCOMBOcenterAlignment on the y axis of the fitted image inside the box if the aspect ratio doesn’t match perfectly.
offset_xINT0-4096–4096Manual pixel offset on the x axis for fine-tuning the placement.
offset_yINT0-4096–4096Manual pixel offset on the y axis for fine-tuning the placement.
thresholdFLOAT0.500–1Mask brightness threshold for detecting the box. 0.5 works for most cases.
padINT00–4096Expands the bounding box outward by N pixels.
use_source_alphaBOOLEANfalseIf true, respects transparency in the source image during paste.
antialiasCOMBOlanczosResampling method used when resizing the source image.
destinationoptIMAGEThe image you’re compositing onto. If not provided, a blank canvas is created.
canvas_woptINT102416–8192Canvas width when no destination image is given.
canvas_hoptINT102416–8192Canvas height when no destination image is given.

Outputs (7)

NameTypeDescription
compositeIMAGE
fitted_sourceIMAGE
placed_maskMASK
xINT
yINT
wINT
hINT