Dieses Python-3-Skript (braucht Pillow) nimmt das Master und optional das PNG nur mit Symbol. Es schreibt ein deckendes 1024-px-iOS-Icon, das 512-px-Play-Icon, die drei Launcher-PNGs für jede Android-Dichte mit dem Symbol in der sicheren Zone des adaptiven Icons und ein quadratisches splash.gif. Führe es lokal aus, oder lade das Skript und deine Bilder in ChatGPT hoch und bitte es, sie auszuführen, falls Codeausführung in deinem Plan verfügbar ist.
#!/usr/bin/env python3
"""Turn one AI-generated master icon into the files a WebViewGold project needs.
Usage:
python3 make_store_icons.py master.png --bg "#0F766E"
python3 make_store_icons.py master.png --fg symbol.png --bg "#0F766E"
master.png square artwork with a solid, full-bleed background
--fg optional: the symbol alone on a transparent background (better adaptive icon)
--bg the background color of your icon; reuse it as the splash screen color
Requires Pillow: pip install Pillow
"""
import argparse
import math
from pathlib import Path
from PIL import Image, ImageDraw
DENSITIES = {"mdpi": 1, "hdpi": 1.5, "xhdpi": 2, "xxhdpi": 3, "xxxhdpi": 4}
OUT = Path("store-icons")
def flatten(img, bg):
"""Composite on a solid color and drop the alpha channel (App Store requirement)."""
img = img.convert("RGBA")
base = Image.new("RGBA", img.size, bg)
base.alpha_composite(img)
return base.convert("RGB")
def square(img):
w, h = img.size
if w != h:
print(f"warning: master is {w}x{h}, cropping to a centered square")
s = min(w, h)
img = img.crop(((w - s) // 2, (h - s) // 2, (w + s) // 2, (h + s) // 2))
return img
def save(img, path):
path.parent.mkdir(parents=True, exist_ok=True)
img.save(path)
print("wrote", path, img.size, img.mode)
def adaptive_foreground(symbol, px):
"""108 dp canvas; the bounding box of the symbol must fit the 66 dp safe circle."""
canvas = Image.new("RGBA", (px, px), (0, 0, 0, 0))
sym = symbol.convert("RGBA")
sym = sym.crop(sym.getbbox() or (0, 0, sym.width, sym.height))
scale = (px * 66 / 108) / math.hypot(sym.width, sym.height)
sym = sym.resize((max(1, round(sym.width * scale)), max(1, round(sym.height * scale))), Image.LANCZOS)
canvas.alpha_composite(sym, ((px - sym.width) // 2, (px - sym.height) // 2))
return canvas
def main():
ap = argparse.ArgumentParser()
ap.add_argument("master")
ap.add_argument("--fg", help="symbol on a transparent background")
ap.add_argument("--bg", default="#FFFFFF")
a = ap.parse_args()
master = flatten(square(Image.open(a.master)), a.bg)
if master.width < 1024:
print(f"warning: master is only {master.width}px; the App Store needs 1024x1024")
# iOS: one opaque 1024 px PNG for the AppIcon set
save(master.resize((1024, 1024), Image.LANCZOS), OUT / "ios" / "AppIcon-1024.png")
# Google Play listing icon: uploaded in the Play Console, not in the project
save(master.resize((512, 512), Image.LANCZOS), OUT / "play" / "play-icon-512.png")
symbol = Image.open(a.fg) if a.fg else None
for name, f in DENSITIES.items():
folder = OUT / "android" / f"mipmap-{name}"
legacy = round(48 * f)
icon = master.resize((legacy, legacy), Image.LANCZOS)
save(icon, folder / "ic_launcher.png")
mask = Image.new("L", (legacy, legacy), 0)
ImageDraw.Draw(mask).ellipse((0, 0, legacy - 1, legacy - 1), fill=255)
rnd = icon.convert("RGBA")
rnd.putalpha(mask)
save(rnd, folder / "ic_launcher_round.png")
fg_px = round(108 * f)
fg = adaptive_foreground(symbol, fg_px) if symbol else master.resize((fg_px, fg_px), Image.LANCZOS)
save(fg, folder / "ic_launcher_foreground.png")
# Splash: square GIF with the symbol on your splash background color
if symbol:
splash = Image.new("RGB", (1024, 1024), a.bg)
s = adaptive_foreground(symbol, 1024)
splash.paste(s, (0, 0), s)
else:
splash = master.resize((1024, 1024), Image.LANCZOS)
save(splash.convert("P", palette=Image.ADAPTIVE), OUT / "splash" / "splash.gif")
if __name__ == "__main__":
main()