# Make a square texture tile: cross-fade each edge band with the half-shifted copy (seams move to the middle, where the image is continuous).
import numpy as np
from PIL import Image
def seamless(im, band=0.22):
    a = np.asarray(im.convert('RGB')).astype(np.float32)
    h, w, _ = a.shape
    shifted = np.roll(np.roll(a, h // 2, axis=0), w // 2, axis=1)
    yy, xx = np.mgrid[0:h, 0:w]
    d = np.minimum(np.minimum(xx, w - 1 - xx) / w, np.minimum(yy, h - 1 - yy) / h)  # 0 at the border … 0.5 in the middle
    m = np.clip(1 - d / band, 0, 1) ** 1.5   # 1 at the border (use the shifted copy, whose middle is seamless) → 0 inside
    out = a * (1 - m[..., None]) + shifted * m[..., None]
    return Image.fromarray(out.clip(0, 255).astype(np.uint8))
