LayerUtility: ImageShift
ImageShift — nudge or wrap-scroll an image, with a border mask thrown in
- image
- mask
- image
- mask
- border_mask
Slides an image sideways and/or vertically by a set number of pixels. With cyclic on, whatever scrolls off one edge wraps back around on the opposite side - the classic "roll" operation, and a fast way to check whether a texture actually tiles seamlessly, since any seam becomes glaringly obvious the moment you wrap it. With cyclic off, the vacated area gets filled with a flat background color instead, which is closer to a simple pan/offset than a wrap.
How it works
shift_x and shift_y set how far the image moves in each direction (negative values shift the other way - there's no separate direction flag, the sign does the work). When wrapping is on, pixels that would fall off one edge reappear on the other, so the total pixel content is preserved, just rearranged. When wrapping is off, the freshly-exposed strip along the shifted edges is painted with background_color, and the node additionally generates a soft border mask around that exposed region - useful if you want to composite something else into exactly the area the shift just vacated, or feather a transition there.
The inputs and outputs that matter
shift_x/shift_y(default 256 each, range ±9999) - how far and which direction to move the image.cyclic(default true) - wrap the edges around, versus expose a flat background.background_color(default black) - the fill color for the exposed area whencyclicis off; irrelevant when wrapping.border_mask_width/border_mask_blur(defaults 20 and 12) - how wide the generated border mask is and how much it's softened at the edge.mask(optional) - shift a companion mask along with the image, in lockstep.
Outputs: the shifted image, the shifted mask (if you supplied one), and border_mask - a mask marking the exposed border region, generated regardless of whether you fed it a mask of your own.
How to install it
Search ComfyUI Layer Style in ComfyUI Manager, or:
cd ComfyUI/custom_nodes
git clone https://github.com/chflame163/ComfyUI_LayerStyle
pip install -r ComfyUI_LayerStyle/requirements.txt
Restart; it's under 😺dzNodes → LayerUtility.
Common issues
If you're using this to test tiling and don't see a seam at all, double-check cyclic is actually on - with it off you're just looking at a flat-filled pan, which will never reveal a tiling problem since nothing's actually wrapping. The other point of confusion: border_mask is generated every single run, wrap or no wrap, cyclic or not - if you don't need it, that's fine, just don't be surprised it's populated even in cyclic mode where there's no literal exposed border in the image itself; it still marks where the border logic would have applied. And a practical note on border_mask_width/border_mask_blur: if you're compositing something into the exposed strip, too little blur leaves a visible hard edge where the mask cuts off, so nudge border_mask_blur up before assuming the compositing step itself is broken.
Inputs (8)
| Name | Type | Default | Description |
|---|---|---|---|
| image | IMAGE | — | |
| shift_x | INT | 256-9999–9999 | — |
| shift_y | INT | 256-9999–9999 | — |
| cyclic | BOOLEAN | true | — |
| background_color | STRING | #000000 | — |
| border_mask_width | INT | 200–999 | — |
| border_mask_blur | INT | 120–999 | — |
| maskopt | MASK | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| border_mask | MASK | — |