Nodes/ComfyUI-BCNodes/Image Resize
ComfyUI Node

Image Resize

Stretch, Pad, Crop or Pillarbox

By 0xBeycan·Created about a month ago·Updated 13 days ago· 2
Image Resize
  • image
  • mask
  • IMAGE
  • width
  • height
  • mask
◄width512►
◄height512►
◄upscale_method▾►
◄keep_proportionstretch►
◄pad_color0, 0, 0►
◄crop_positioncenter►
◄divisible_by2►
◄device▾►

ComfyUI's stock resize node does one thing: you hand it a width and a height and it squashes your image into them. This one gives you the dropdown you were missing. Stretch, fit inside, pad, pad with edges, pad with a blurred cover, crop to aspect, or target a total pixel count - all of them the same node, with the mask carried along.

Why the modes matter

Padding and cropping are the difference between "my subject is now 20% narrower" and "my subject is intact". If you've ever fed a 2:3 photo into an SDXL pipeline built for 1:1, you've met the problem:

  • stretch (the default) - exactly width × height, aspect ignored. Correct when you genuinely don't care, which is less often than people use it.
  • resize - the largest size that fits inside width × height at the source aspect. The safe, boring choice; nothing gets distorted and nothing gets cut.
  • crop - crop to the target aspect first, then resize. crop_position picks where the window sits: center, top, bottom, left, right.
  • pad, pad_edge, pad_edge_pixel, pillarbox_blur - resize, then fill the difference out to width × height. pad uses pad_color; pad_edge the mean of the image's outer rows and columns; pad_edge_pixel repeats the edge pixels outward; pillarbox_blur is the one people screenshot - the frame itself scaled to cover, blurred, desaturated and dimmed, sitting behind a clean centre.
  • total_pixels - width × height pixels total, at the source aspect. Use it when what you care about is compute, not dimensions.

The mask goes along for the ride: it's scaled bilinearly to the image's size if it differs, then cropped and resampled with it, and padded with its own edge values. Without a mask wired, a padded image gives you the padding as the mask (1 = padding), which is a genuinely clever way to get a "don't generate here" mask out of a letterbox for free.

The other inputs

  • width, height - 0 to 16384. A 0 means "keep the source side" under stretch, or "free" under the proportional modes. Default is 512 × 512, which will quietly wreck things if you forget to set it.
  • upscale_method - nearest-exact, bilinear, area, bicubic, lanczos, nvidia_rtx_vsr. Lanczos runs on the CPU through PIL on 8-bit frames, exactly like ComfyUI's own lanczos. nvidia_rtx_vsr needs the nvidia-vfx package and an RTX card, and rounds the size to a multiple of 8.
  • divisible_by - default 2, up to 512. Both sides get floored to a multiple of this; a padded image instead grows its padding to the next multiple. Set it to 8 or 64 when the result has to survive a VAE or a latent-space operation.
  • device - cpu or gpu. Everything except lanczos resamples through torch on the chosen device.

Outputs are the ones you'd want: IMAGE, width, height (the actual output size after all that flooring), and mask.

Two behaviours worth knowing

An image that's already the output size comes back untouched, without a copy, and a crop window that needs no resampling isn't resampled - so lanczos doesn't round your pixels through 8-bit for nothing. Those are the kinds of decisions that matter when you chain five resizes and wonder why the image looks tired.

Unreadable settings raise instead of guessing. A pad_color it can't parse, or a value count that doesn't match the image's channels, is an error naming the fix; same for anything that would produce a zero-pixel side. That's better than padding black, but it does mean typos surface as failures rather than bad images.

Install

Manager, searching the pack title ComfyUI-BCNodes, or:

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

Restart and search BCNodes in the node library. requirements.txt is opencv-python, postfx and caption-audit, none of which this node needs - but install them anyway if you want the pack's PostFx and Caption Audit nodes to exist. Delete a leftover ComfyUI-AutoBypass folder from the pack's old name.

Where people get burned

divisible_by default 2 is nearly useless and also nearly harmless - set it deliberately to 8 or 16 for anything heading into a VAE, or the "why did my image lose four pixels" bug reports start. The tooltip is explicit that padding grows rather than floors, so a 1024 target with divisible_by 64 can end up at 1088.

lanczos with device set to gpu raises - that's documented, not a bug, since the lanczos path is PIL on the CPU. And nvidia_rtx_vsr needs both the package and the hardware; if you don't have an RTX card, it fails rather than falling back.

Last: pillarbox blur returns one mask per incoming mask frame, not one per image frame. If you're compositing onto the padded result, that difference will find you.

CategoryBCNodes/image

Inputs (10)

NameTypeDefaultDescription
imageIMAGE—
widthINT5120–163840 = the source width (or free, when the proportion is kept).
heightINT5120–163840 = the source height (or free, when the proportion is kept).
upscale_methodCOMBOlanczos runs on the CPU (PIL, 8-bit); nvidia_rtx_vsr needs the nvidia-vfx package and an NVIDIA RTX GPU and rounds the size to a multiple of 8.
keep_proportionCOMBOstretchstretch: exactly width x height. resize: the largest size inside width x height at the source aspect. pad / pad_edge / pad_edge_pixel / pillarbox_blur: resize, then pad out to width x height with pad_color / the edge mean / the edge pixels / a blurred cover of the frame. crop: crop to the target aspect, then resize. total_pixels: width x height pixels at the source aspect.
pad_colorSTRING0, 0, 0Padding colour for pad: 'r, g, b' in 0-255 or 0-1, #rrggbb, a colour name or one grey value.
crop_positionCOMBOcenterWhere the crop window sits (crop), or where the image sits inside the padding (pad modes).
divisible_byINT20–512Floor both sides to a multiple of this; padding grows to the next multiple instead. 0 or 1 = off.
maskoptMASK—
deviceoptCOMBODevice the frames are processed on (not for lanczos).

Outputs (4)

NameTypeDescription
IMAGEIMAGE—
widthINT—
heightINT—
maskMASK—