Image Pad For Outpaint Target Size (Swwan)
Fit a picture into an exact canvas without stretching it
- image
- mask
- IMAGE
- MASK
Two things you might want from a "pad for outpaint" node. The first is "add 400 pixels on the left," which is what the sibling masked node does. The second is "make this fit a 1920×1080 frame" - an exact destination size, aspect ratio preserved, no stretching, letterboxed into place.
That's this node, and the fact that it letterboxes rather than crops puts it in the same family as the video world's pillarboxing: you keep the whole original, and the empty space is what the model fills.
Inputs and outputs
Required: image (IMAGE), target_width (INT, default 0, step 8), target_height (INT, default 0, step 8), feathering (INT, default 0, step 1), upscale_method (enum: nearest-exact, bilinear, area, bicubic, lanczos).
Optional: mask (MASK).
Outputs: IMAGE and MASK - the same contract as the masked node, so anything downstream that expects "padded image + generate-here mask" works with either.
How it decides the geometry
It computes scaling_factor = min(target_width / W, target_height / H). Because that's a minimum of two ratios, it's the "fit inside the box" factor - the image always ends up fully inside the target, never overflowing.
If that factor is less than 1 - the image is bigger than the target in at least one axis - the image is downscaled by exactly that factor using upscale_method, and the mask is nearest-resized to match. If it's 1 or more, no scaling happens at all: the image is used as-is.
Then the remaining space is split evenly around it (the leftovers from an odd number of pixels go to the bottom/right), and the actual padding is delegated to the masked variant, which means you get the same grey canvas fill, the same feathering ramp, and the same mask convention: 1 over the new area, 0 over the original, feathered at the boundary.
That "only downscales, never upscales" behavior is worth internalizing. Ask for 4096×4096 from a 1024×1024 image and you get your 1024 image centered in a big grey field - not an upscale. If you wanted the image itself bigger, upscale it first and then let this node place it.
The trap in the defaults
target_width and target_height both default to 0, and the scaling factor is computed unconditionally - min(0/W, 0/H) is 0, which is less than 1, so the node tries to resize the image to zero pixels. You get an exception, not a no-op.
Set both explicitly. This is a node where the defaults are not a usable configuration, and it's the first thing to check if it errors the moment you add it to a graph.
The other numbers to respect: the target dimensions are step-8 for a reason - VAE downsampling and latent grid alignment. Pick 1920×1088 over 1920×1085, and read upscale_method with some care: lanczos or bicubic for photographic content, area when you're downscaling noisy generations, nearest-exact only when you actually want hard pixels (pixel art, masks).
Feathering, again
Same implementation detail as the masked node: the feather ramp is a per-pixel Python loop, and if feathering * 2 isn't smaller than both image dimensions, the whole feathering step is skipped and you get a hard edge. Keep it small - single digits to low teens - and it does what you'd expect.
Where it fits
Standard outpaint-to-format: load any aspect ratio → this node to a fixed target → encode with the mask → sample at high denoise → done, you have a 16:9 or 9:16 asset that didn't crop anything. Useful for prepping thumbnails, video frames, and print-ratio canvases from whatever image you happened to generate.
Install
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/aining2022/ComfyUI_Swwan.git
cd ComfyUI_Swwan
python -m pip install -r requirements.txt
Windows portable:
.\python_embeded\python.exe -m pip install .\ComfyUI\custom_nodes\ComfyUI_Swwan\requirements.txt
Restart ComfyUI, hard-refresh the browser, search Swwan; it's under Swwan/Advanced/Image. No model downloads, no inference - this is a resize-and-center operation on tensors you already have in memory.
Because it shares its IMAGE/MASK output contract with the masked variant, the two are drop-in swappable in an existing outpaint workflow: if you decide "actually I want a fixed output size" halfway through wiring, swap the node and leave everything downstream alone.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| target_width | INT | 00–16384 | — |
| target_height | INT | 00–16384 | — |
| feathering | INT | 00–16384 | — |
| upscale_method | COMBO | 5 options: nearest-exact, bilinear, area, bicubic, lanczos | |
| maskopt | MASK | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| IMAGE | IMAGE | — |
| MASK | MASK | — |