InOutPaint
Extend the canvas before you outpaint into it
- image
- image
Don't let the name confuse you: InOutPaint doesn't run any diffusion, and it doesn't generate a mask. What it does is the unglamorous prep step every outpainting workflow needs first - placing your existing image inside a bigger blank canvas at a specific position, so there's actually empty space for a sampler to fill in afterward. It's the same job core ComfyUI's own "Pad Image for Outpainting" node does, minus the mask output - pair it with a mask node of your own before it hits a sampler.
This matters because outpainting only works if the graph knows exactly where the new pixels are. You can't just resize a canvas and hope; you need to say "the original image goes here, and everything else is new territory."
The inputs and outputs that matter
image- your source image.width/height(default 512 each) - the size of the new, larger canvas.align_top,align_left,align_bottom,align_right- where the original image sits inside that canvas. These four together define the box the source image occupies; whatever falls outside that box, up towidth/height, is the new blank area you'll be outpainting into.
One image output - the padded canvas, ready to feed a mask generator and then a sampler.
How to install it
Search ComfyUI-HakuImg in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone --recurse-submodules https://github.com/licyk/ComfyUI-HakuImg
Restart ComfyUI and find it under Image → HakuImg. No models, no dependency on the pack's submodule - plain canvas math.
Common issues & troubleshooting
Nothing looks different after running it. Check your align_* values against width/height. The defaults put align_bottom and align_right at 512 - the same as the default canvas size - which means with defaults left untouched, the source image fills the canvas edge to edge and there's no blank space at all. You have to deliberately set these smaller than the canvas dimensions to carve out room to outpaint into.
Part of the source image got clipped off. If your alignment values plus the source image's own dimensions add up to more than width or height, the overflow gets cut. Do the arithmetic before running: canvas size needs to comfortably fit the original image at the position you've chosen, plus whatever margin you want generated.
Expected a mask output and didn't get one. This node only handles the canvas geometry - it doesn't produce a mask marking which area is new. For a full context-aware inpainting/outpainting pipeline (crop, edit the new region, stitch back with the rest of the image untouched), you'll want to pair this with a proper mask node and, ideally, look at a dedicated crop-and-stitch pack for the actual regeneration step - that's a different job than this node does.
Inputs (7)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| width | INT | 512 | — |
| height | INT | 512 | — |
| align_top | INT | 0 | — |
| align_left | INT | 0 | — |
| align_bottom | INT | 512 | — |
| align_right | INT | 512 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |