Image Mask Scale As (UTK)
Scale an image and its mask to match any reference — no manual math
- scale_as
- image
- mask
- image
- mask
- original_size
- width
- height
The annoying thing about compositing in ComfyUI is that every image has to agree on size, and you usually find out they don't when a cat on a tensor mismatch fails your whole run. Image Mask Scale As (UTK) is the fix for the specific case where you want one image - and its mask - to take on the exact dimensions of another image. Feed it a scale_as reference and it rescales your image (and optional mask) to that reference's width and height, all in one node.
It comes from the ComfyUI-UniversalToolkit grab-bag, so its siblings do the inverse job: ImageScaleRestore_UTK takes the original_size box this node emits and can put the image back where it started. The two make a clean round trip for workflows that shrink something, process it, then restore it - a pattern that shows up constantly in face-detail and tile pipelines.
How it works
The node takes the first frame of scale_as, reads its pixel dimensions, and treats that as the target canvas. Then the fit mode decides what happens to your image on that canvas:
resize- scale proportionally, no padding. The output is whatever size the scaled image actually is, which may be smaller than the reference. This tripped people up; the v1.4.7 changelog exists specifically because resize and pad used to behave identically. They don't anymore.pad/pad_edge/pad_edge_pixel- scale to fit and pad the rest to the target size, usingpad_color.stretch- force it to exactly match, distortion be damned.crop- scale to cover and crop the overflow, anchored bycrop_position.pillarbox_blur- scale, then fill the leftover with a blurred, dimmed copy of the image itself. That's the cinematic 16:9 letterbox look.
The method dropdown is your resize sampler (lanczos default, which is the right call for downscaling). crop_position centers by default but you can pin to top/bottom/left/right.
Inputs and outputs that matter
For a beginner, the three that actually matter are scale_as (the image whose size you're copying), image, and mask. If you only feed scale_as and no image, the node still builds a canvas of that size. pad_color is a preset list - black, white, gray, plus the primaries - which is nicer than typing hex.
Outputs: image and mask (both resized in lockstep), then original_size (a BOX), width, and height. Wire original_size into ImageScaleRestore_UTK to undo the resize later, or use width/height for anything that needs numbers - e.g. an Empty Latent node for a matching resolution.
Install and gotchas
Install via ComfyUI Manager (search "ComfyUI-UniversalToolkit") or:
cd ComfyUI/custom_nodes
git clone https://github.com/whmc76/ComfyUI-UniversalToolkit
cd ComfyUI-UniversalToolkit
pip install -r requirements.txt
Then restart ComfyUI. No model downloads, no API keys - this is pure PIL math, so it runs on CPU if it has to. The only real dependency weight is Pillow, numpy and torch, which you already have.
Where people get burned: forgetting that resize doesn't fill to the target, and then wondering why the mask doesn't line up with the reference. If you need exact output dimensions, use pad, not resize. The other classic gotcha is feeding it a batch in scale_as - it only reads the first frame, so batch sizes in the two image inputs should match or it'll recycle the last one.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| scale_as | IMAGE | — | |
| fit | COMBO | 7 options: stretch, resize, pad, pad_edge, pad_edge_pixel, crop, +1 | |
| method | COMBO | 6 options: lanczos, bicubic, hamming, bilinear, box, nearest | |
| imageopt | IMAGE | — | |
| maskopt | MASK | — | |
| pad_coloropt | COMBO | black | 9 options: black, white, gray, red, green, blue, +3 |
| crop_positionopt | COMBO | center | 5 options: center, top, bottom, left, right |
Outputs (5)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| original_size | BOX | — |
| width | INT | — |
| height | INT | — |