Does an AI image tile seamlessly? A wraparound check in Pillow

Asking for a seamless pattern does not guarantee one. Compare the left and right edges and preview a 2x2 tiling to test a Sume image before you ship it.

5 min readSume
All posts

To test whether a generated image tiles, compare its opposite edges and look at it tiled. If the average difference across the wrap seam (last column against first column, bottom row against top row) is not close to the difference between ordinary neighboring columns, the pattern will show a line when repeated. Generate with Sume, run the check below, and only ship patterns that pass.

A prompt that says "seamless repeating pattern" is a request, not a guarantee. The Sume Image API returns whatever the model produces, and nothing in the request schema promises edge-matching, so the check belongs in your pipeline.

What does the check measure?

It reduces the seam question to one ratio per axis.

Seam ratio, read 2026-10-04
TermMeaningReading
Wrap differenceMean absolute difference between last and first column (or row)What a tiled viewer sees at the seam
Neighbor differenceMean absolute difference between adjacent columns (or rows) inside the imageThe image's normal texture change
Seam ratioWrap difference divided by neighbor differenceNear 1 is invisible; much above 2 is a visible line (a starting threshold to tune)

What is the script?

It reads a local file you downloaded from the data[].url Sume returned, prints both ratios and saves a 2x2 tiling you can open to check by eye. It needs Pillow and NumPy.

import sys
import numpy as np
from PIL import Image

img = Image.open(sys.argv[1]).convert("RGB")
a = np.asarray(img, dtype=float)

def ratio(x):
    wrap = np.abs(x[:, 0] - x[:, -1]).mean()
    near = np.abs(x[:, 1:] - x[:, :-1]).mean() or 1e-6
    return wrap / near

rx, ry = ratio(a), ratio(a.transpose(1, 0, 2))
print(f"horizontal seam ratio {rx:.2f}, vertical {ry:.2f}")

w, h = img.size
sheet = Image.new("RGB", (w * 2, h * 2))
for i in range(2):
    for j in range(2):
        sheet.paste(img, (i * w, j * h))
sheet.save("tiled-2x2.png")
print("ok" if max(rx, ry) < 2 else "visible seam: regenerate or fix")

What if the pattern fails?

Generate again with n above 1 and keep the passing candidates; the catalog lists each model's n range and billing is per image, so four candidates cost four images. If none pass, offset the image by half its width and height, then use a masked edit on the visible cross to repaint only the seam. Sume's mask_url edit is documented for ChatGPT Image 2.5; check the catalog for other models before relying on it.

When is a perfect tile worth the effort?

It matters for fabric and wallpaper print, game textures and web backgrounds that repeat across a wide screen. For a one-off hero image it does not matter at all. Keep the test out of those flows and run it only where the image will repeat.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume