Die-cut sticker outline from a transparent gpt-image-2.5 PNG in Pillow

Request background=transparent on Sume, then add a white die-cut border by growing the alpha channel with MaxFilter. Code, border width math, and print notes.

5 min readSume
All posts

Ask openai/gpt-image-2.5 for background: "transparent" with output_format: "png", then grow the alpha channel with ImageFilter.MaxFilter to get a solid white border and composite the artwork on top. A MaxFilter size of 2k+1 expands the shape by k pixels on every side, so a size of 25 gives a 12 pixel border, about 1.2 percent of a 1024 pixel image.

Why this model for stickers

Of the Sume image models, only ChatGPT Image 2.5 and its Sunburst variant accept background in the catalog. Other models return 400 unsupported_parameter for it, so a transparent sticker source needs this model, or a cutout step on another model's output.

A die-cut sticker has an outline that follows the artwork. That is the border step here, and the shape it gives is what a cutter follows.

Grow the alpha and composite

Take the alpha channel, apply MaxFilter(size) (size must be odd), and fill that shape with white. Then paste the artwork over it using its own alpha. The filter is a square kernel, so corners grow slightly more than diagonals; for round borders blur and threshold after.

import os, io, requests
from PIL import Image
H = {"Authorization": "Bearer " + os.environ["SUME_API_KEY"]}
def gen(**body):
    r = requests.post("https://api.sume.com/v1/images", json=body, headers=H, timeout=60)
    r.raise_for_status()
    if r.status_code == 202:
        raise SystemExit("queued, read /v1/jobs/{id}/result: " + r.text)
    return r.json()
def fetch(u):
    return Image.open(io.BytesIO(requests.get(u, timeout=60).content))
from PIL import ImageFilter
out = gen(model="openai/gpt-image-2.5", background="transparent", output_format="png",
          prompt="Cute cartoon avocado with sunglasses, thick clean outline, sticker art")
art = fetch(out["data"][0]["url"]).convert("RGBA")
k = 12
pad = Image.new("RGBA", (art.width + 4 * k, art.height + 4 * k), (0, 0, 0, 0))
pad.paste(art, (2 * k, 2 * k))
alpha = pad.getchannel("A")
grown = alpha.filter(ImageFilter.MaxFilter(2 * k + 1))
grown = grown.filter(ImageFilter.GaussianBlur(2)).point(lambda v: 255 if v > 100 else 0)
base = Image.new("RGBA", pad.size, (255, 255, 255, 0))
base.putalpha(grown)
base.paste((255, 255, 255, 255), mask=grown)
Image.alpha_composite(base, pad).save("sticker.png")
print("border px", k, "cost", out["usage"]["cost"])

Pick the border width

Ask your printer for the border width their cutter needs; a few millimeters is a common starting point. Convert millimeters to pixels with your print resolution.

Border width at 300 dpi, arithmetic read 2026-10-05
BorderPixels at 300 dpiMaxFilter size
2 mm2449
3 mm3571
1 mm1225

Gotchas

  • The MaxFilter is slow on large images. Work at the final print size, not at 4K.
  • Soft glows or shadows in the generated art carry faint alpha that the border will include. Ask for clean edges in the prompt.
  • The border adds pixels to the canvas, so pad first as shown, or the border is clipped at the image edge.
  • Keep the sticker as PNG with alpha, and send a separate cut path if your printer asks for one.

Related recipes

To compare a model's transparent output with a cutout from another model, read transparent PNG vs cutout. Do not re-save through JPEG between steps, see PNG between passes. A sticker set made of squares can reuse the circle-crop recipe.

Sources

Related posts

More in Media tools

All Media tools posts

Written by Sume