Seamless Offset For Inpaint ✦
The classic 50%-offset seamless trick, packaged into two nodes
- image
- shifted_image
- seam_mask
- shift_y
- shift_x
Before latent tiling made seamless generation easy, the community's standard trick was embarrassingly mechanical: generate your image, shift it 50% so the seams land in the middle, mask over them, inpaint, then shift back. People were doing this manually back in the A1111 days - one guy famously described spending hours on it and concluding it was "way over my head" before the tooling caught up. This node is that whole trick, packaged as a single step.
The logic is sound: diffusion models inpaint worst at image edges and best near the center, where the model has the most context. Shifting the seam to the center is the one thing that makes inpaint actually want to fix it. SeamlessOffsetForInpaint does the shifting and builds the mask, and its partner SeamlessOffsetReverse puts everything back afterward.
How it works
The node does two things. First it rolls the image by 50% on whichever axes you enable (torch.roll - the right half wraps around to the left, no stretching). Then it builds a feathered cross mask centered exactly where the seams now live: full opacity (1.0) on the seam line, falling off smoothly with a cosine curve to 0.0 at the mask edges.
The key detail is that it hands you the shift amounts back as outputs (shift_y, shift_x), so the reverse step is guaranteed to be the exact inverse. No math on your part, and no off-by-one mismatches.
The workflow
Image → [SeamlessOffsetForInpaint] → shifted_image → VAE Encode → KSampler (inpaint)
seam_mask ─────────────────┘
shift_x / shift_y ──→ [SeamlessOffsetReverse] → Save
Everything downstream is standard ComfyUI inpainting: VAE-encode the shifted image, feed the mask, let the sampler refill the masked region, decode, and run SeamlessOffsetReverse with shift_x/shift_y wired from the offset node's outputs.
Inputs and outputs worth caring about
- mask_width (default 64) - total width of the mask band in pixels. Needs to cover the visible seam plus blending room; 48–96 is the typical range. Too narrow and the inpaint leaves a thin scar.
- feather (default 32) - soft falloff on each side of the band. 0 gives a hard-edged mask; higher values blend the repair into surrounding content. The node clamps it to
mask_widthinternally, so you can't feather wider than the band. - offset_x / offset_y - shift and mask each axis independently. For a pattern that only needs to tile horizontally, disable
offset_yand you'll only mask the one seam you actually have.
Outputs: shifted_image (IMAGE), seam_mask (MASK), shift_y (INT), shift_x (INT). The two INTs exist to feed the reverse node - don't ignore them.
Install and gotchas
Same pack, same install: ComfyUI Manager (search "ComfyUI-seamless_latent_tiling") or
cd ComfyUI/custom_nodes
git clone https://github.com/mikemojen/ComfyUI-seamless_latent_tiling
then restart; the node is under image/seamless. No dependencies beyond PyTorch, no model files.
Two things bite people. First, if your inpaint result shows a visible rectangular patch, widen mask_width or raise feather - the model needs room to blend, not a surgical strip. Second, don't skip the reverse node. Forgetting it gives you a "correct" seamless image that's shifted 50%, which looks broken until you realize what happened. Honest verdict: this route is slower and fiddlier than generating seamless in the first place with SeamlessLatentTiling. Reach for it when you already love an image and can't regenerate - as a repair tool it's the reliable one.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| mask_width | INT | 648–512 | Total width of the inpaint mask band in pixels. Should be wide enough to cover the visible seam plus blending room. 48–96 is typical. |
| feather | INT | 320–256 | Soft falloff zone in pixels on each side of the mask band. 0 = hard-edged mask. Higher values = smoother blend into surrounding content. Should be ≤ mask_width. |
| offset_x | BOOLEAN | true | Shift horizontally and mask the vertical seam. |
| offset_y | BOOLEAN | true | Shift vertically and mask the horizontal seam. |
Outputs (4)
| Name | Type | Description |
|---|---|---|
| shifted_image | IMAGE | — |
| seam_mask | MASK | — |
| shift_y | INT | — |
| shift_x | INT | — |