Nodes/ComfyUI-BCNodes/Image Scale By Aspect Ratio
ComfyUI Node

Image Scale By Aspect Ratio

The resize node that takes the mask with it

By 0xBeycan·Created 24 days ago·Updated 4 days ago· 2
Image Scale By Aspect Ratio
  • image
  • mask
  • image
  • mask
  • original_size
  • width
  • height
◄aspect_ratio▾►
◄proportional_width1►
◄proportional_height1►
◄fit▾►
◄method▾►
◄round_to_multiple▾►
◄scale_to_side▾►
◄scale_to_length1024►
◄background_color#000000►

Resizing an image is easy. Resizing an image and its mask to the same geometry, on a ratio the model was actually trained for, with the resulting width and height available as numbers for the rest of the graph - that's the gap this node fills.

What it is

Optional image and mask inputs, a pile of widgets, and five outputs: the resized image, the resized mask, original_size as a BOX, plus width and height as integers.

The widget set splits cleanly in two. The ratio side decides shape: aspect_ratio (original, custom, 1:1, 3:2, 4:3, 16:9, 2:3, 3:4, 9:16, with proportional_width / proportional_height defining the custom one) and fit (letterbox, crop, fill). The size side decides how many pixels: scale_to_side (None, longest, shortest, width, height, total_pixel(kilo pixel)) and scale_to_length. method picks the resampling kernel, round_to_multiple forces the result onto a grid, and background_color is the letterbox fill.

How it works

In order: the aspect ratio fixes the shape, scale_to_side plus scale_to_length fix the size with fractions truncated, then both sides round up to the nearest multiple of round_to_multiple. Then fit decides what happens to the pixels that don't match - letterbox fits the whole image inside and pads with background_color, crop centre-crops to the target ratio, and fill stretches, which is the one you almost never want.

Two behaviours are worth knowing precisely, because they're deliberate choices rather than accidents:

  • The MASK output is never None. No mask wired, or ComfyUI's placeholder mask, and you get zeros at the output size. That's kinder than a dead branch downstream, and it means "no mask" degrades into "mask of nothing" rather than a crash.
  • Mismatched inputs raise. A mask that doesn't match the image size, or neither an image nor a mask wired at all, throws instead of returning None everywhere. That's the opposite choice, made on purpose: silently resizing a mask you didn't intend to resize is worse than an error.

Why the ratio side matters more than the size side

Every architecture has resolutions it likes. SDXL's trained ratios are a discrete list (1024×1024, 1152×896, 1216×832, 1344×768, 1536×640 and their rotations); the Flux-era models mostly take any resolution in a megapixel band but want dimensions divisible by 64. The community fix for "I need 16:9" has always been generate at a trained ratio, then crop - 7:4 then crop, rather than asking for 1920×1080 up front and getting distorted anatomy.

This node is the mechanical version of that advice: pick 7:4-ish from the preset list or a custom ratio, pin the long edge with scale_to_side = longest, put round_to_multiple on 64 for a Flux-family model or 8 for SDXL-era ones, and take width and height off the outputs into whatever builds your latent. Those two INT outputs are the quietly useful part - they're the only way to keep a chain of nodes from disagreeing about the resolution.

For plain "more pixels", method wants lanczos; it adds no detail, can't hallucinate, and is instant. For mask work where you're resizing down, nearest keeps edges honest.

The mask output

Wire mask into your inpaint or composite path and you've solved the alignment problem in one hop: image and mask were resized by the same node, at the same time, to the same geometry. Doing this with two separate resize nodes is the single most common cause of a mask that's offset by a handful of pixels after an upscale.

Installing it

ComfyUI Manager → search ComfyUI-BCNodes → install → restart. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/0xBeycan/ComfyUI-BCNodes
pip install -r ComfyUI-BCNodes/requirements.txt

Reload the browser tab after restarting; the inputs sit under BCNodes/image, and requirements.txt is only there for the pack's PostFx and Caption Audit nodes.

Where people get burned

Letterboxing black bars into your own generation. Feeding a letterboxed image back into an img2img or detail pass means sending black bars to the model, and models happily render black bars. Use crop, or crop the output yourself.

Rounding up quietly changes your number. Ask for 1000 on a round_to_multiple of 64 and you get 1024. The width / height outputs are the truth - read those, don't recompute in your head.

scale_to_side = None means no resizing. You're reshaping only. If the output looks untouched, that's why.

fill is a stretch, and it looks like it. For anything with a face in it, use the other two.

CategoryBCNodes/image

Inputs (11)

NameTypeDefaultDescription
aspect_ratioCOMBO9 options: original, custom, 1:1, 3:2, 4:3, 16:9, +3
proportional_widthINT11–100000000—
proportional_heightINT11–100000000—
fitCOMBO3 options: letterbox, crop, fill
methodCOMBO6 options: lanczos, bicubic, hamming, bilinear, box, nearest
round_to_multipleCOMBO8 options: 8, 16, 32, 64, 128, 256, +2
scale_to_sideCOMBO6 options: None, longest, shortest, width, height, total_pixel(kilo pixel)
scale_to_lengthINT10244–100000000—
background_colorSTRING#000000—
imageoptIMAGE—
maskoptMASK—

Outputs (5)

NameTypeDescription
imageIMAGE—
maskMASK—
original_sizeBOX—
widthINT—
heightINT—