Nodes/comfyui-311-inpaint/Add Margins 311
ComfyUI Node

Add Margins 311

The one-node square pad that collapses a four-node chain

By Latentnaut·Created 2 months ago·Updated 2 months ago· 0
Add Margins 311
  • image
  • mask
  • IMAGE
  • MASK
size_modesquare_longest
scale_by1.25
margin_layoutsymmetric
unitpixels
extra_width0
extra_height0
left0
left_unitpixels
right0
right_unitpixels
top0
top_unitpixels
bottom0
bottom_unitpixels
target_width512
target_height512
fill_color#000000
haligncenter
valigncenter

Almost every outpainting workflow starts with the same boring move: stick your image on a bigger canvas, centered, with empty space around it to generate into. ComfyUI's stock way to do that is a four-node chain - ImageSize, ScaleByAspectRatio, Upscale By, Image Align - which is exactly as fiddly as it sounds. Add Margins 311 is the whole chain compressed into one node, with one crucial bonus: it pads the mask too, and keeps it registered with the image.

That bonus is the point. Inpaint nodes only work if the mask lines up pixel-for-pixel with the image you feed the sampler. Stretch the image one way and the mask another - easy to do by accident when you're stitching four padding nodes together - and your inpaint quietly generates in the wrong place. Add Margins 311 moves the image and its mask onto the same canvas in one tensor operation, so they can't drift apart.

What it actually does

The default square_longest mode matches that four-node chain exactly: take the longest side of your image, build a black 1:1 canvas at longest_side * scale_by (1.25 by default), and center the content on it without resampling. A 500×712 image becomes an 890×890 canvas. That's padding, not stretching - exactly what you want when the canvas space is the region you're going to mask and regenerate. The 1.25 default is a sensible bit of headroom; you get a wide border to outpaint into instead of a sliver.

The other two modes cover the cases where square doesn't fit:

  • add_margins - symmetric (extra_width / extra_height, in pixels or percent) or fully custom per-side left / right / top / bottom, each with its own unit. Use this when you only want to extend one edge, like extending a portrait upward for more headroom.
  • target_size - contain-fit the image onto an absolute target_width × target_height canvas. This one does resample (lanczos for the image, bilinear for the mask) to fit, so it's the mode for forcing a non-square image into a model's native resolution box.

Everything else is what you'd expect and mostly ignorable: fill_color for the canvas background (the default #000000 - and note it accepts #RGB or #RRGGBB only), plus halign / valign for where the content sits if you don't want it dead center.

Outputs are IMAGE and MASK, both on the same canvas. Wire them into your sampler (or the now-common pattern of padding with a solid color and prompting the model to "remove the red/black padding" - the 2026 outpainting trick - where fill_color is doing real work).

Installing it

The pack is tiny and dependency-free - no model downloads, just torch and ComfyUI's own comfy.utils:

cd ComfyUI/custom_nodes && git clone https://github.com/Latentnaut/ComfyUI-311-Inpaint

then restart ComfyUI. ComfyUI Manager users can search "comfyui-311-inpaint" instead.

The gotchas

Two things will bite you, and neither is the node's fault. First, it's written against ComfyUI's newer backend API (comfy_api.latest, io.ComfyNode, no NODE_CLASS_MAPPINGS). If it doesn't load, that's not a broken pack - it's an old ComfyUI. Update first; this style requires a recent build.

Second, the node is strict about input shapes. Feed it a mask that doesn't match the image's size or batch count and it raises a ValueError instead of silently doing something wrong - annoying, but it's the check that keeps your inpaint aligned. If you hit it, resize your mask upstream or skip the mask input entirely and add the pad to the mask after.

Reality check: this is a one-node pack ("311 series" currently ships exactly this node), a single initial commit, zero community footprint - the author is a Reddit regular, not an established node dev. But it's a clean, readable, MIT-licensed ~50-line pad utility, and for the core job - square-pad an image plus its mask without resampling - it does it in one node where the stock alternative needs four.

Category311/Inpaint

Inputs (21)

NameTypeDefaultDescription
imageIMAGE
size_modeCOMBOsquare_longestsquare_longest: square canvas = longest_side * scale_by, center content. add_margins: expand with symmetric or custom side margins. target_size: fit onto target_width x target_height.
scale_byFLOAT1.250.01–8Multiplier for longest side when size_mode=square_longest (default 1.25).
margin_layoutCOMBOsymmetricsymmetric: extra_width/height split equally L/R and T/B. custom: independent left/right/top/bottom (each with own unit).
unitCOMBOpixelsUnit for extra_width / extra_height when margin_layout=symmetric.
extra_widthINT00–8192Total added width (split L/R). Used when size_mode=add_margins + symmetric.
extra_heightINT00–8192Total added height (split T/B). Used when size_mode=add_margins + symmetric.
leftFLOAT00–8192Left margin (custom layout).
left_unitCOMBOpixels2 options: pixels, percent
rightFLOAT00–8192Right margin (custom layout).
right_unitCOMBOpixels2 options: pixels, percent
topFLOAT00–8192Top margin (custom layout).
top_unitCOMBOpixels2 options: pixels, percent
bottomFLOAT00–8192Bottom margin (custom layout).
bottom_unitCOMBOpixels2 options: pixels, percent
target_widthINT5121–8192Canvas width when size_mode=target_size.
target_heightINT5121–8192Canvas height when size_mode=target_size.
fill_colorSTRING#000000Canvas fill color as #RGB or #RRGGBB.
halignCOMBOcenter3 options: center, left, right
valignCOMBOcenter3 options: center, top, bottom
maskoptMASK

Outputs (2)

NameTypeDescription
IMAGEIMAGE
MASKMASK