Resize To Canvas Size
Hit an exact canvas without doing the crop math in your head
- image
- IMAGE
- padding_mask
You know the drill: your checkpoint wants exactly 1024×1024, but your source render is 832×1216, and suddenly you're mentally computing aspect ratios and wondering whether to crop, pad, or just let the thing distort. ComfyUI's built-in resizers either scale by a factor or force a target size and pray. Resize To Canvas Size is the one-node answer: it takes any image, gets it onto an exact target canvas, and lets you decide precisely which part of the image survives.
The selling point is the Photoshop-style 3×3 anchor grid at the top of the node. Click a cell and you're telling the node "keep this corner/edge of the image, crop or pad everything on the other side." Clicking top_left pins the image's top-left to the canvas corner; center keeps the middle and crops both edges evenly. It's a small thing, but it replaces a whole chain of crop/paste geometry nodes.
How it works
Under the hood it's three steps, all in the node's nodes.py:
- Scale - pick one of five
scale_methods. "Fit to Canvas short edge" scales so the image's shortest edge matches the canvas's shortest edge (the one you want for a centered crop); "Fit to Canvas long edge" scales so the longest edge fits (the one you want for letterboxing); "Fit to Canvas height/width" match one axis exactly; "None" leaves the image at original resolution, so the canvas acts as a crop window. - Fill - with
fill_method: crop, the scaled image is pasted at the anchor position, overflow is trimmed, and any gaps get filled with yourpadding_fill. Withstretch, it just distorts to fill the canvas and ignores the anchor entirely. Stretch is rarely the answer - if the aspect mismatch is severe it looks like a funhouse mirror. - Mask - the
padding_maskoutput is1.0where padding was added and0.0where original pixels landed. All zeros when nothing got padded.
The inputs that matter
width/height- target canvas in pixels (1–8192). These are the only numbers you should ever have to care about.anchor- the 9-value grid (top_left,center, … ). The node's custom widget turns this into clickable cells.scale_methodandfill_method- the two choices above that decide whether you crop or letterbox.padding_fill-black,white,gray_50,transparent,custom, ornoise.customrevealscustom_color_hex(native colour picker) plus the optionalcustom_color_hex_inputSTRING connector, which overrides the picker with any#RRGGBB/#RRGGBBAAstring - handy if another node is computing the colour for you. Invalid values silently fall back to the picker.noiserevealsnoise_seedand fills gaps with reproducible random noise.
Outputs: IMAGE (always RGBA) and padding_mask.
Install
ComfyUI Manager: search "ComfyUI-ResizeToCanvasSize". Or the manual route:
cd ComfyUI/custom_nodes
git clone https://github.com/Carasibana/ComfyUI-ResizeToCanvasSize.git
Then restart ComfyUI. That's it - there's no requirements.txt and no model download; it runs on the Pillow/numpy/torch ComfyUI already ships. Refreshingly rare.
Where people get burned
- The padding mask is 1 = padding. If you're used to masks where white = the subject, this is backwards - but it's backwards on purpose. Wire
padding_maskinto an inpainting setup and white is exactly the region you want regenerated, so you get fill-in-the-blanks for free instead of having to invert anything. - Output is always RGBA. If a downstream node chokes on four channels, throw in a Convert Image node.
- The custom hex input must be
#RRGGBBor#RRGGBBAA. Anything else is ignored, not an error.
Recipes that actually work
- Square crop, keep centre:
Fit to Canvas short edge+crop+center. - Letterbox/pillarbox:
Fit to Canvas long edge+crop+black. - Cookie-cutter crop at original res:
None+crop- the canvas dims are your crop window, the anchor picks what survives.
It's a simple node with a thankless job, but it does that job exactly. If you chain it into a KSampler with padding_mask as your inpaint region, you've got a repeatable "fit my content to the canvas, regenerate the gaps" pipeline that needs zero hand-computed coordinates.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| width | INT | 5121–8192 | — |
| height | INT | 5121–8192 | — |
| anchor | COMBO | center | 9 options: top_left, top_center, top_right, middle_left, center, middle_right, +3 |
| scale_method | COMBO | Fit to Canvas short edge | 5 options: None – use original size, Fit to Canvas short edge, Fit to Canvas long edge, Fit to Canvas height, Fit to Canvas width |
| fill_method | COMBO | crop | 2 options: crop, stretch |
| padding_fill | COMBO | black | 6 options: black, white, gray_50, transparent, custom, noise |
| custom_color_hex | STRING | #000000 | — |
| noise_seed | INT | 00–18446744073709550000 | — |
| custom_color_hex_inputopt | STRING | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| padding_mask | MASK | — |