Android adaptive icon: 108 dp layers, 66 dp safe zone, from Sume

Adaptive icon layers are 108 x 108 dp with a 66 x 66 dp visible zone and 18 dp margins. Generate a transparent foreground on Sume and scale it inside the zone.

5 min readSume
All posts

Android's adaptive icon is two required layers, foreground and background, each 108 x 108 dp. The visible area after the device mask is the central 66 x 66 dp, and the 18 dp on every side is reserved for masking and effects. The practical job for an image model is the foreground: a transparent mark that fits inside the 66 dp zone.

The numbers

Android's page gives these dimensions. A monochrome layer is optional, and the page ties it to themed icons from Android 13 (API 33). Layers can be vector drawables, which Android prefers, or bitmaps.

Android adaptive icon dimensions (read 2026-10-03)
ItemValue in dpShare of 108 dp layer
Layer size108 x 108100%
Visible zone66 x 6661.1%
Margin per side1816.7%
Logo minimum48 x 4844.4%

Pixel budget

A bitmap layer for xxxhdpi, which is 4 pixels per dp, is 432 x 432 pixels with a 264 x 264 pixel visible zone. The density factor is Android's own convention and not on the page quoted here, so confirm it against the density table in the Android docs before you ship. The script below produces the 432 pixel foreground and keeps the mark inside the 264 pixel zone, which is the safe choice for any density because everything scales together.

Generate and place

Request a transparent PNG square from ChatGPT Image 2.5, trim to the visible bounding box, scale it to fit 264 x 264, and center it on a transparent 432 x 432 canvas. Keep the background layer a separate flat color or gradient, because the system moves the layers against each other for parallax and pulse effects, and a foreground that contains its own backdrop defeats that.

import os, io, requests
from PIL import Image
r = requests.post(
    "https://api.sume.com/v1/images",
    headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
    json={"model": "openai/gpt-image-2.5", "aspect_ratio": "1:1", "prompt": "single bold leaf-shaped mark, flat color, no text, no backdrop", "background": "transparent", "output_format": "png"},
    timeout=90,
)
r.raise_for_status()
if r.status_code != 200:
    raise SystemExit("202: read the finished job from /v1/jobs/{id}/result")
img = Image.open(io.BytesIO(requests.get(r.json()["data"][0]["url"], timeout=60).content))
art = img.convert("RGBA")
box = art.getbbox()
if box:
    art = art.crop(box)
art.thumbnail((264, 264), Image.LANCZOS)
layer = Image.new("RGBA", (432, 432), (0, 0, 0, 0))
layer.alpha_composite(art, ((432 - art.width) // 2, (432 - art.height) // 2))
layer.save("ic_launcher_foreground.png", optimize=True)

Checking the result on a device mask

Android's own page explains why the margin exists: the system applies different mask shapes per device and animates the layers against each other, so the outer 18 dp can be cut away or moved. Preview your foreground inside a circle and a rounded square before you accept it. If any part of the mark touches the edge of the 66 dp zone, shrink it; the page's logo range is 48 to 66 dp, so the mark does not need to fill the whole zone. Avoid shadows baked into the bitmap, since the system can add its own effects and a baked shadow will double up. A flat mark generated with no backdrop is the right input; if the model returns a faint halo around the shape, trim it by thresholding the alpha channel before scaling.

Limits of this approach

A generated bitmap is not a vector drawable, so it will not stay sharp at every size the way Android's preferred vector layers do. Use it for a first foreground and for store art, and redraw the mark as a vector if the app is long-lived. The monochrome layer for themed icons is a solid shape whose alpha is the mask; derive it by filling the foreground's non-transparent pixels with one color rather than asking a model for it. Transparency on Sume is documented for ChatGPT Image 2.5, with Image 1.0 transparency: true named as the other route.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume