Nodes/ComfyUI-XJNodes/Image Batch Resize (Pad/Crop)
ComfyUI Node

Image Batch Resize (Pad/Crop)

Batch Resizing Without the Stretch Marks

By alexjx·Created 11 months ago·Updated 8 days ago· 0
Image Batch Resize (Pad/Crop)
  • image_1
  • image_2
  • image_3
  • image_4
  • image_5
  • image_6
  • image_7
  • image_8
  • images
◄width1024►
◄height1024►
◄resize_modepad►

You've got three images from three different places - a 1216x832 SDXL render, a 512x768 crop from a phone, a 1920x1080 frame you pulled out of a video - and everything downstream wants one tensor at one size. Core ComfyUI's ImageBatch will do the merge, but it does it by forcing the second image into the first one's dimensions, which is a polite word for squashing it. Image Batch Resize (Pad/Crop) is the version that doesn't squash: give it a target box and it fits each image inside it, either letterboxing it or trimming the edges.

That's the whole pitch: usable batch, no warped faces.

Where it actually earns its slot

ComfyUI's IMAGE type is a single 4D tensor - [batch, height, width, channels] - so a "batch" is only a batch if every frame shares dimensions. The moment your sources disagree you have to reconcile them, and there are only two honest ways to do that without distorting content: pad or crop.

The KB's resolution notes are why this matters more than it sounds. Every architecture has a native aspect ratio, and off-ratio input is where doubled heads and elongated bodies come from. Padded black borders are ugly. A stretched 16:9 face is worse.

Typical uses: prepping references for an img2img pass, normalising frames for an image-to-video model that wants uniform dimensions, or collating several branches into one batch to save together.

The mechanism, since it's short

The source is about forty lines, and worth knowing.

For pad, the scale factor is min(width/source_w, height/source_h) - shrink to fit - so the whole image survives and bars fill the rest. For crop, it's max(...) - fill the box and cut the overflow. Both preserve aspect ratio up to pixel rounding. Resizing is bilinear with antialiasing, the same resampler ComfyUI uses for most image scaling. Offsets are centred, except when the leftover is an odd number of pixels - then the extra one lands on the right or bottom edge.

Then it concatenates: image_1 through image_8, in that order, batches intact. Four frames plus two gives you six, in the positions you wired them. Anything disconnected or None is skipped - the standard engine convention where an unwired optional socket simply doesn't arrive.

Inputs and output

image_1 is required. image_2 through image_8 are optional, so the node is a one-input passthrough when you don't need it and an eight-way merger when you do.

The three widgets you'll set: width and height (INT, 1–16384, defaulting to 1024x1024) and resize_mode (pad or crop, default pad). If you're feeding a VAE, stay on multiples of 8 - and 64 if you're on Flux, per the KB's divisibility note. The node will happily produce 1000x1000; the encode step is where off-grid sizes bite.

One output, images, type IMAGE. It goes into VAE Encode, a latent-batch sampler, Save Image, or the image input of a video node. It also chains into itself: past eight inputs, wire one node's output into the next's image_1 at the same width/height. The second pass is a no-op resize.

What it does not output is a MASK, because padding is real black pixels rather than emptiness. This is not an outpainting tool; that's a different node with a mask output.

Install

Manager is the sane path: search ComfyUI-XJNodes and install. Manually:

cd ComfyUI/custom_nodes
git clone https://github.com/alexjx/ComfyUI-XJNodes
# restart ComfyUI

Note the README's own clone command still says github.com/yourusername/ComfyUI-XJNodes.git. It's a placeholder that never got fixed - use the URL above. There's no pip step for this node: requirements.txt in the repo is empty, and the libraries it leans on (PIL, aiohttp, torch) ship with ComfyUI already.

The pack itself is a self-described personal-use collection - loaders, savers, text list pickers, a loop system, an image comparer - so installing it for this one node drops a few dozen others into your menu too. Fine, useful, single-maintainer.

Things that bite

Mixed channels raise an error. All inputs must have the same channel count, so a 4-channel image wired next to a 3-channel one throws "All inputs must have the same number of channels." Strip alpha upstream and you're fine.

High-denoise img2img eats your bars. This is the real trap with pad. You letterbox a portrait into a square, then run img2img at 0.7 denoise, and the sampler happily invents content where the black was. Pad is for size reconciliation, not for generous margins you intend to keep.

crop throws away pixels silently. A 16:9 image in a square box loses about a third of its width. Do the math before batching a shoot.

If every image in your workflow is already the same size, you don't need this node; core ImageBatch or RepeatImageBatch will do. The moment they aren't, this is the one I'd reach for.

CategoryXJNodes/image

Inputs (11)

NameTypeDefaultDescription
image_1IMAGE—
widthINT10241–16384—
heightINT10241–16384—
resize_modeCOMBOpad2 options: pad, crop
image_2optIMAGE—
image_3optIMAGE—
image_4optIMAGE—
image_5optIMAGE—
image_6optIMAGE—
image_7optIMAGE—
image_8optIMAGE—

Outputs (1)

NameTypeDescription
imagesIMAGE—