Smart Resize Images
Resize a whole batch to a target megapixel count without wrecking the aspect ratio
- images
- images
- widths
- heights
You've got a folder of images at mixed resolutions and every one needs to end up roughly the same size - and, because it's ComfyUI and latents are picky, that size has to be divisible by 64. Manually computing 1024×1024-ish dimensions per image is exactly the kind of busywork that should be a node. Smart Resize Images is that node: give it a target pixel count and it resizes each image to match, preserving aspect ratio, rounding to your divisibility requirement, and cropping instead of distorting when the rounding would bend the image out of shape.
Quick reality check so you set expectations: this is a normalizer, not an upscaler. The upscaling doc in the wider ecosystem distinguishes hard - "more pixels, source already sharp" is a Lanczos/ESRGAN job, not a resize node. If a 512px image isn't going to gain real detail from being pushed to 1MP, and this node won't fabricate any. It's for making a mixed batch uniform and latent-friendly.
How it works
For each image it computes the ideal dimensions from the target pixel count while keeping the original aspect ratio:
ideal_w = sqrt(target_pixels * aspect_ratio)
ideal_h = target_pixels / ideal_w
then rounds both to the nearest multiple of divisible_by (default 64). Two paths after that:
- If the rounded size distorts the aspect ratio by less than
distortion_threshold(default 0.005, i.e. half a percent), it just resizes straight to those dimensions. The rounding error is invisible. - If the rounding would stretch the image noticeably, it instead resizes to cover the target (scaling up enough that the whole area is filled) and then crops the excess. Where it crops is decided by
crop_position. The interesting default,auto, measures the standard deviation of the left vs right (or top vs bottom) strips and keeps the more detailed side - so you don't crop the face out of a portrait. Nice touch, and one you'd only find by reading the source.
There's also an upscale_to switch. Default match_divisible_by means: if the image is smaller than the target, don't inflate it to the full pixel count - just nudge it to the nearest multiple of 64. Choose target_pixels and it will always hit the target, upscaling small images as needed. And upscale_method picks the resampler: bicubic (torch, good default), lanczos (PIL, sharpest for downscales), or area (best when shrinking a lot, anti-aliased).
Inputs and outputs
Inputs: images, target_pixels (default 1048576 ≈ 1MP), divisible_by (64), distortion_threshold (0.005), crop_position (auto/center/left/right/top/bottom), upscale_to, upscale_method. Outputs: images, plus widths and heights - both lists of INTs, so you can read back the actual dimensions each image got. Those dimension outputs are genuinely useful if a downstream node needs to know the sizes.
Install
ComfyUI Manager (search "ComfyUI-GadgetNodes"), or:
cd ComfyUI/custom_nodes
git clone https://github.com/2daadv/ComfyUI-GadgetNodes.git
pip install -r ComfyUI-GadgetNodes/requirements.txt
Restart; under Gadget/image. No models.
Where people get burned
divisible_bydefaults to 64 - that's latent territory. If you're resizing for a sampler you'll usually want 64 (or 8 for some pipelines); if you're prepping for a pixel-space consumer, a smaller number gives you finer control over final size.- Crop loss is real. Any image whose aspect ratio doesn't match the target within the threshold gets cropped, and cropping removes content. The
autoposition picks the more-detailed side, which is the right bias, but check your outputs if faces or subjects sit near the edges. Raisedistortion_thresholdif you'd rather accept slight stretch than lose edges. - It's not an upscaler. Pushing a small, soft image to
target_pixelsjust makes it a bigger soft image. For real upscaling you want a proper upscaler after this node, not this node alone.
For batch-prep work - datasets, contact sheets, a grid of uniform gens - this is the node you reach for. It quietly solves the "everything must be divisible by 64 and roughly the same size" problem in one pass.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| images | IMAGE | — | |
| target_pixels | INT | 104857664–16777216 | — |
| divisible_by | INT | 648–128 | — |
| distortion_threshold | FLOAT | 0.0050–0.1 | — |
| crop_position | COMBO | auto | 6 options: auto, center, left, right, top, bottom |
| upscale_to | COMBO | match_divisible_by | 2 options: target_pixels, match_divisible_by |
| upscale_method | COMBO | bicubic | 3 options: bicubic, lanczos, area |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| images | IMAGE | — |
| widths | INT | — |
| heights | INT | — |