Este script de Python 3 (necesita Pillow) toma el maestro y, opcionalmente, el PNG con solo el símbolo. Genera un icono opaco de 1024 px para iOS, el icono de 512 px para Play, los tres PNG del launcher para cada densidad de Android con el símbolo dentro de la zona segura adaptativa y un splash.gif cuadrado. Ejecútalo en local, o sube el script y tus imágenes a ChatGPT y pídele que lo ejecute si tu plan incluye ejecución de código.
#!/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()