〽️ Image Ops Pad Out
The letterboxing node that doesn't touch a single pixel of your image
- fill_color
- image
- image
- mask
- width
- height
Adding black bars around an image sounds like the most boring node possible, right up until you need to squeeze a 1024×576 render into a 9:16 canvas for an outpaint pass, or letterbox 16:9 footage into a square slot on a video wall. That's the entire job of ImageOps PadOut: it grows the canvas on any side with solid black padding and leaves your actual content untouched. No scaling, no cropping, no interpolation - the pixels you put in are the pixels you get back, just sitting in a bigger frame.
The clue is in the name: this is the "pad out" step from compositing, the thing you do before you hand frames to something that cares about exact dimensions. The snap_to_multiple input spells out the real motivation - the tooltip says to use 16 for "Wan/VACE-friendly output sizes." Video models and some inpainting pipelines are grumpy about off-grid dimensions; being able to snap your canvas to a multiple of 16 while you pad is a small thing that saves you a "can't encode this latent" error later.
How it works
Under the hood it's exactly as simple as it sounds. The node makes a new tensor of zeros sized to source + pad_left + pad_right by source + pad_top + pad_bottom, drops your image in offset by the top/left padding, and zero-fills the rest. The mask it also hands you is the clever bit: it's 1 over the padded area and 0 over your original content (unless you flip invert_mask, which marks the source instead). That mask is genuinely useful - wire it into an inpaint region, use it to know where you added real estate, or multiply it against something to keep the effect out of the border.
The inputs that matter
You don't need to touch most of these. The three that count:
pad_left / pad_top / pad_right / pad_bottom- per-side padding in pixels. Default is 128 on every side, which is a fat border; don't be surprised if your first run comes back with a chunky black frame. Drop them to 0 first if you just want to test.snap_to_multiple- quantizes each pad value to a multiple. Set to 16 for video-friendly sizes. One gotcha: the actual padding snaps, so if you type 130 with a snap of 16, you get 128.aspect_ratio- this is a UI helper, not a backend feature. The tooltip says it plainly: the frontend turns a preset like 16:9 or 1:1 into explicit pad values; the backend uses whatever pad values it receives. If you change the preset and the border doesn't move, remember it's just computing numbers for you.
bypass is the standard pack-wide escape hatch - it returns the input unchanged with zero padding.
Outputs
image, mask, plus width and height as INTs. Those last two are the sleeper feature: wire them straight into a resolution node or an Empty Latent so your downstream generation matches the padded canvas instead of guessing.
Installing it
This is part of the ComfyUI-Majoor-ImageOps pack, installed like any custom node:
cd ComfyUI/custom_nodes
git clone https://github.com/MajoorWaldi/ComfyUI-Majoor-ImageOps
Or use ComfyUI Manager and search for "ComfyUI-Majoor-ImageOps". Then restart ComfyUI and hard-refresh the browser - Ctrl+F5, or Cmd+Shift+R on macOS - or the frontend bits (including the live preview) won't show up. No pip dependencies and no model files; it only uses torch, PIL, and numpy, which ComfyUI already has. Needs ComfyUI ≥ 0.13.0.
Where people get burned
The padding is always solid black. There's no color option, so if you wanted a white matte you're out of luck - Composite it onto a Constant-colored canvas instead. And remember the default mask semantics: it highlights the padding, not the source. Feed it into a mask pipeline the wrong way around and you'll be inpainting the border instead of the image. Check invert_mask before you assume it's broken.
Inputs (11)
| Name | Type | Default | Description |
|---|---|---|---|
| bypass | BOOLEAN | false | — |
| pad_left | INT | 1280–4096 | — |
| pad_top | INT | 1280–4096 | — |
| pad_right | INT | 1280–4096 | — |
| pad_bottom | INT | 1280–4096 | — |
| target_format | COMBO | custom | Add extra padding to hit a target aspect ratio without scaling the image. |
| fill_mode | COMBO | constant | 4 options: constant, edge_extend, reflect, blurry |
| fill_color | COLOR | #000000 | — |
| blur_radius | INT | 320–512 | Used by blurry padding. |
| invert_mask | BOOLEAN | false | By default the output mask marks the *padded* area as 1 and the original source as 0. Toggle to invert (source=1, padding=0). |
| imageopt | IMAGE,VIDEO | Images/Video input. Accepts IMAGE batches and VIDEO frame sources. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| width | INT | — |
| height | INT | — |