Pad Image by Aspect for Outpaint
Pad the canvas, draw the mask, let the dice decide — outpainting prep in one node
- image
- Image
- Mask
- Params
The first thing to know: this node never generates a single pixel. It's the stage-hand of a masked outpainting workflow. It builds the canvas, parks your image on it, and hands back a feathered mask that tells the sampler "keep this, regenerate that." If you've built an outpaint graph by hand before - pad image, make empty latent at the right size, wire up a noise mask - this collapses those first steps into one node. And it does it with dice, if you want.
Why bother with masked outpainting at all in 2026? The KB's inpainting essay makes the honest case: instruction-edit models like Flux Klein and Qwen-Image-Edit took over most canvas extension, and for a one-off "what's behind this wall" it's hard to beat prompting a solid-colored padding away. But masked outpainting still wins when the original must survive byte-for-byte, or when you're extending in several passes and don't want drift compounding. This node is squarely in that camp: the interior of your image stays untouched, and only the padded area (plus a feathered border) gets regenerated.
How it works
The math is simple and worth knowing because it explains the surprises. The node takes your image, computes what the target aspect ratio should be, then rounds the canvas to a multiple of 8 - ComfyUI latent territory. Rotation, if any, is applied before the canvas is sized, so the rotated bounding box is what gets padded. Then scale_pct shrinks the original image inside that fixed canvas. Order matters: canvas first, shrink second.
The mask is the part that makes or breaks the output. Padded area is 1 (regenerate), the interior of your original image is 0 (keep), and within feathering pixels of the border the mask ramps from 0 to 1 with a quadratic falloff. That ramp is your seam prevention - it forces the sampler to blend across the outer few pixels of your original instead of leaving a hard cut line. This is exactly the "generous mask overlap" advice in the KB's outpainting section, baked into a slider.
The inputs that matter
You don't need to touch all eight. The ones that earn your attention:
aspect_ratio- presets from16:9down to1:1, orrandom, which picks a fresh ratio every run.placement-center, the four directions, or the full 3x3 grid. Chooserandomfor uniform placement anywhere on the canvas.feathering(default 40) - mask softness. Higher = smoother blend into the padded area.bg_color- white, black, or grey. For the modern "pad with a color, prompt it away" trick you'd want an arbitrary color, and this node doesn't offer one - pick the closest of the three.
Then the outputs. Image is the padded tensor; Mask is what you wire into Set Latent Noise Mask or an inpaint conditioning node; Params is a string like AR: 16:9, Placement: center, Scale: 100%, Rotation: 0°. That string is more useful than it looks - when you run random, it's the only record of what the node actually decided.
Installing it
No model downloads, no requirements.txt, no Python deps beyond the torch ComfyUI already ships. Either ComfyUI Manager → Install from URL → paste https://github.com/vaishnav-vn/va1, or:
cd ComfyUI/custom_nodes
git clone https://github.com/vaishnav-vn/va1.git
Then restart ComfyUI. It registers as Pad Image by Aspect for Outpaint under the va1 category.
Where people get burned
- The seed input is a lie. It's accepted but never read by the code - it only exists so you can bump it and force a re-execution, which re-rolls the random choices. The picks use Python's global
random, so you cannot lock a seed and reproduce a layout. It's a re-roll button, not a seed. UseParamsto log what happened. - 1:1 quietly caps the scale. On
1:1the node drops the top scale options, so the image always ends up smaller than the canvas - no "extend to exactly 1:1" with zero padding. By design, but surprising the first time. - Huge feathering does nothing. The falloff only runs while
2 * featheringis smaller than the scaled image's height and width. Crankfeatheringpast that on a small image and you silently get a hard edge. - Directional placement falls back to center. Ask for
lefton a portrait target and the node quietly centers it. The orientation just doesn't permit it.
For a batch pass, set aspect_ratio, placement, and scale_pct to random, keep the seed moving, and let Params tell you what each frame got. That's where this node earns its keep - one deterministic canvas helper that turns into a composition dice roller.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| aspect_ratio | COMBO | 16:9 | 8 options: random, 16:9, 9:16, 3:2, 2:3, 4:5, +2 |
| placement | COMBO | center | 14 options: center, random, left, right, up, down, +8 |
| scale_pct | COMBO | 100 | 7 options: random, 50, 60, 70, 80, 90, +1 |
| rotation | COMBO | 0 | 13 options: random, 0, 30, 60, 90, 120, +7 |
| bg_color | COMBO | white | 3 options: white, black, grey |
| seed | INT | 00–2147483647 | — |
| feathering | INT | 400–1024 | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| Image | IMAGE | — |
| Mask | MASK | — |
| Params | STRING | — |