AI board game tokens: transparent PNG art, circle-cropped at 300 dpi

Make board game character tokens: one anchor style, a transparent PNG per character from gpt-image-2.5, then crop to a circle in Pillow at token size.

5 min readSume
All posts

For board game tokens, generate one anchor character in the game's style, then request each other character with the anchor as an input_reference and background: "transparent" on openai/gpt-image-2.5. A token is small, so a 1024x1024 image is more than enough: a 1-inch token at 300 dpi is only 300 pixels.

Crop each character to a circle in code at the final token size, so every token has the same edge and the same margin.

Token size in pixels (read 2026-10-04)

Print size times dpi gives the pixel size you need. All of these fit inside one 1024x1024 generation with room to spare.

Token diameters at 300 dpi (read 2026-10-04)
Token diameterPixels at 300 dpiDownscale from 1024
0.75 in2254.55x
1 in3003.41x
1.5 in4502.28x
2 in6001.71x

Each character, same style

Describe the character, keep the style line word for word, and say what to leave out (no frame, no text, because the circle and the name are made in code).

{
  "model": "openai/gpt-image-2.5",
  "prompt": "Same painted fantasy style as the reference. A dwarf blacksmith, chest-up portrait, centred, filling most of the frame. Nothing behind the character, no frame, no text.",
  "input_references": [
    {"type": "image_url", "image_url": {"url": "https://example.com/anchor-elf.png"}}
  ],
  "background": "transparent",
  "output_format": "png",
  "aspect_ratio": "1:1"
}

Circle-crop at token size

This runs as is on a generated placeholder: it shrinks to 300 pixels, masks to a circle and keeps the alpha channel.

from PIL import Image, ImageDraw

art = Image.new("RGBA", (1024, 1024), (180, 60, 60, 255))  # replace with Image.open("dwarf.png")
size = 300  # 1 inch at 300 dpi
art = art.resize((size, size), Image.LANCZOS)
mask = Image.new("L", (size, size), 0)
ImageDraw.Draw(mask).ellipse((0, 0, size - 1, size - 1), fill=255)
token = Image.new("RGBA", (size, size), (0, 0, 0, 0))
token.paste(art, (0, 0), mask)
token.save("token.png")
print(token.size, token.mode)

Keeping the set consistent

gpt-image-2.5 takes up to 16 references, so you can pass the anchor plus the previous one or two characters. Rerun a token whose face style drifted instead of tolerating it; a failed generation is not billed, and a completed one is billed at the endpoint's pricing line.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume