Adaptive Image Scaler
A resize node that actually knows when to call in the upscaler
- image
- upscale_model
- IMAGE
ComfyUI has a million resize nodes, and most of them are dumb about one thing: they'll cheerfully push a 1024px image through a 4x ESRGAN upscaler even when you only wanted it 5% bigger - or worse, run a multi-GB model on an image you're actually shrinking. Adaptive Image Scaler is the one that pays attention. Give it a target size, optionally wire in an upscale model, and it decides on its own whether to bother with the ML model at all.
That decision is the whole point. The node computes a geometric mean scale from your width and height targets - sqrt(scale_w * scale_h) - and only engages the ML upscaler when that number is above 1.08x. Below that threshold, or if no upscale_model is connected, it just resizes with plain interpolation. That threshold is deliberate: an ESRGAN-style model at 1.05x mostly adds noise and eats VRAM for no gain. You'd be surprised how many workflows would run faster if their resize step made this call.
What it does when the ML path engages
If you are upscaling meaningfully and an upscale_model is attached, it gets clever:
- Tiled upscaling - starts with 512px tiles at 32px overlap, so big images don't blow your VRAM on one giant forward pass.
- Progressive tile reduction - if you hit an out-of-memory error, the tile size shrinks by 0.75x and it retries, down to a 128px minimum. That's a genuine fallback safety, not just a crash.
- Synchronized alpha - a 4-channel RGBA image gets its RGB upscaled by the model while the alpha channel is scaled separately with bicubic interpolation, then recombined. Most resize nodes quietly flatten your alpha; this one doesn't.
Then the result is pulled to your exact target with ComfyUI's common_upscale, so the output is precisely target_width × target_height, not whatever the upscaler happened to produce.
The inputs that matter
image- anything on an IMAGE socket.target_width/target_height- the dimensions you want out.interpolation-lanczos(clean upscales),bicubic,bilinear,area(best for downscaling),nearest-exact. If you're shrinking,areais the right call.dimension_alignment(default 0) - rounds the target down to a multiple of this number. Set 64 if your pipeline wants dimensions aligned to the model's latent grid.upscale_model(optional) - the UPSCALE_MODEL socket from an UpscaleModelLoader. Leave it unplugged and the node is a plain, very good resize.
Output is a single IMAGE, ready to feed anything downstream.
Install
Everything in this pack installs the same way. ComfyUI Manager → search "uber_comfy_nodes" (listed as "Suplex Misc ComfyUI Nodes") → install → restart. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/saftle/uber_comfy_nodes
Then restart ComfyUI. No model downloads, no heavy dependencies - the requirements are just Pillow, numpy, psutil and pynvml, all of which you almost certainly already have. The node lands under the Uber Comfy menu.
Where people get burned
dimension_alignment floors the target, so asking for 1200px with alignment 64 gives you 1152. If the exact pixel count matters, request aligned dimensions yourself. Also note the tiling only happens in the ML path - if you're doing a plain interpolation resize of a huge image, it happens in one shot and can be slow, but that's normal. And one honest caveat: below 1.08x the upscaler never fires, which is a feature, but if you're used to a "4x always" upscaler you'll need to resize in steps to get the model involved.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| target_width | INT | — | |
| target_height | INT | — | |
| interpolation | COMBO | 5 options: lanczos, bicubic, bilinear, area, nearest-exact | |
| dimension_alignment | INT | 00–256 | — |
| upscale_modelopt | UPSCALE_MODEL | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |