diff --git a/brand/icon.svg b/brand/icon.svg index 3813302..2277788 100644 --- a/brand/icon.svg +++ b/brand/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/brand/icons/apple-touch-icon.png b/brand/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/brand/icons/apple-touch-icon.png and b/brand/icons/apple-touch-icon.png differ diff --git a/brand/icons/favicon.ico b/brand/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/brand/icons/favicon.ico and b/brand/icons/favicon.ico differ diff --git a/brand/icons/icon-16.png b/brand/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/brand/icons/icon-16.png and b/brand/icons/icon-16.png differ diff --git a/brand/icons/icon-192.png b/brand/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/brand/icons/icon-192.png and b/brand/icons/icon-192.png differ diff --git a/brand/icons/icon-32.png b/brand/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/brand/icons/icon-32.png and b/brand/icons/icon-32.png differ diff --git a/brand/icons/icon-48.png b/brand/icons/icon-48.png new file mode 100644 index 0000000..219285a Binary files /dev/null and b/brand/icons/icon-48.png differ diff --git a/brand/icons/icon-512.png b/brand/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/brand/icons/icon-512.png and b/brand/icons/icon-512.png differ diff --git a/brand/icons/icon.svg b/brand/icons/icon.svg index 3813302..2277788 100644 --- a/brand/icons/icon.svg +++ b/brand/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/crypto_monitor_binance/static/icons/apple-touch-icon.png b/crypto_monitor_binance/static/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/crypto_monitor_binance/static/icons/apple-touch-icon.png and b/crypto_monitor_binance/static/icons/apple-touch-icon.png differ diff --git a/crypto_monitor_binance/static/icons/favicon.ico b/crypto_monitor_binance/static/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/crypto_monitor_binance/static/icons/favicon.ico and b/crypto_monitor_binance/static/icons/favicon.ico differ diff --git a/crypto_monitor_binance/static/icons/icon-16.png b/crypto_monitor_binance/static/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/crypto_monitor_binance/static/icons/icon-16.png and b/crypto_monitor_binance/static/icons/icon-16.png differ diff --git a/crypto_monitor_binance/static/icons/icon-192.png b/crypto_monitor_binance/static/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/crypto_monitor_binance/static/icons/icon-192.png and b/crypto_monitor_binance/static/icons/icon-192.png differ diff --git a/crypto_monitor_binance/static/icons/icon-32.png b/crypto_monitor_binance/static/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/crypto_monitor_binance/static/icons/icon-32.png and b/crypto_monitor_binance/static/icons/icon-32.png differ diff --git a/crypto_monitor_binance/static/icons/icon-512.png b/crypto_monitor_binance/static/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/crypto_monitor_binance/static/icons/icon-512.png and b/crypto_monitor_binance/static/icons/icon-512.png differ diff --git a/crypto_monitor_binance/static/icons/icon.svg b/crypto_monitor_binance/static/icons/icon.svg index 3813302..2277788 100644 --- a/crypto_monitor_binance/static/icons/icon.svg +++ b/crypto_monitor_binance/static/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/crypto_monitor_gate/static/icons/apple-touch-icon.png b/crypto_monitor_gate/static/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/crypto_monitor_gate/static/icons/apple-touch-icon.png and b/crypto_monitor_gate/static/icons/apple-touch-icon.png differ diff --git a/crypto_monitor_gate/static/icons/favicon.ico b/crypto_monitor_gate/static/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/crypto_monitor_gate/static/icons/favicon.ico and b/crypto_monitor_gate/static/icons/favicon.ico differ diff --git a/crypto_monitor_gate/static/icons/icon-16.png b/crypto_monitor_gate/static/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/crypto_monitor_gate/static/icons/icon-16.png and b/crypto_monitor_gate/static/icons/icon-16.png differ diff --git a/crypto_monitor_gate/static/icons/icon-192.png b/crypto_monitor_gate/static/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/crypto_monitor_gate/static/icons/icon-192.png and b/crypto_monitor_gate/static/icons/icon-192.png differ diff --git a/crypto_monitor_gate/static/icons/icon-32.png b/crypto_monitor_gate/static/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/crypto_monitor_gate/static/icons/icon-32.png and b/crypto_monitor_gate/static/icons/icon-32.png differ diff --git a/crypto_monitor_gate/static/icons/icon-512.png b/crypto_monitor_gate/static/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/crypto_monitor_gate/static/icons/icon-512.png and b/crypto_monitor_gate/static/icons/icon-512.png differ diff --git a/crypto_monitor_gate/static/icons/icon.svg b/crypto_monitor_gate/static/icons/icon.svg index 3813302..2277788 100644 --- a/crypto_monitor_gate/static/icons/icon.svg +++ b/crypto_monitor_gate/static/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/crypto_monitor_gate_bot/static/icons/apple-touch-icon.png b/crypto_monitor_gate_bot/static/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/crypto_monitor_gate_bot/static/icons/apple-touch-icon.png and b/crypto_monitor_gate_bot/static/icons/apple-touch-icon.png differ diff --git a/crypto_monitor_gate_bot/static/icons/favicon.ico b/crypto_monitor_gate_bot/static/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/crypto_monitor_gate_bot/static/icons/favicon.ico and b/crypto_monitor_gate_bot/static/icons/favicon.ico differ diff --git a/crypto_monitor_gate_bot/static/icons/icon-16.png b/crypto_monitor_gate_bot/static/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/crypto_monitor_gate_bot/static/icons/icon-16.png and b/crypto_monitor_gate_bot/static/icons/icon-16.png differ diff --git a/crypto_monitor_gate_bot/static/icons/icon-192.png b/crypto_monitor_gate_bot/static/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/crypto_monitor_gate_bot/static/icons/icon-192.png and b/crypto_monitor_gate_bot/static/icons/icon-192.png differ diff --git a/crypto_monitor_gate_bot/static/icons/icon-32.png b/crypto_monitor_gate_bot/static/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/crypto_monitor_gate_bot/static/icons/icon-32.png and b/crypto_monitor_gate_bot/static/icons/icon-32.png differ diff --git a/crypto_monitor_gate_bot/static/icons/icon-512.png b/crypto_monitor_gate_bot/static/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/crypto_monitor_gate_bot/static/icons/icon-512.png and b/crypto_monitor_gate_bot/static/icons/icon-512.png differ diff --git a/crypto_monitor_gate_bot/static/icons/icon.svg b/crypto_monitor_gate_bot/static/icons/icon.svg index 3813302..2277788 100644 --- a/crypto_monitor_gate_bot/static/icons/icon.svg +++ b/crypto_monitor_gate_bot/static/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/crypto_monitor_okx/static/icons/apple-touch-icon.png b/crypto_monitor_okx/static/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/crypto_monitor_okx/static/icons/apple-touch-icon.png and b/crypto_monitor_okx/static/icons/apple-touch-icon.png differ diff --git a/crypto_monitor_okx/static/icons/favicon.ico b/crypto_monitor_okx/static/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/crypto_monitor_okx/static/icons/favicon.ico and b/crypto_monitor_okx/static/icons/favicon.ico differ diff --git a/crypto_monitor_okx/static/icons/icon-16.png b/crypto_monitor_okx/static/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/crypto_monitor_okx/static/icons/icon-16.png and b/crypto_monitor_okx/static/icons/icon-16.png differ diff --git a/crypto_monitor_okx/static/icons/icon-192.png b/crypto_monitor_okx/static/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/crypto_monitor_okx/static/icons/icon-192.png and b/crypto_monitor_okx/static/icons/icon-192.png differ diff --git a/crypto_monitor_okx/static/icons/icon-32.png b/crypto_monitor_okx/static/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/crypto_monitor_okx/static/icons/icon-32.png and b/crypto_monitor_okx/static/icons/icon-32.png differ diff --git a/crypto_monitor_okx/static/icons/icon-512.png b/crypto_monitor_okx/static/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/crypto_monitor_okx/static/icons/icon-512.png and b/crypto_monitor_okx/static/icons/icon-512.png differ diff --git a/crypto_monitor_okx/static/icons/icon.svg b/crypto_monitor_okx/static/icons/icon.svg index 3813302..2277788 100644 --- a/crypto_monitor_okx/static/icons/icon.svg +++ b/crypto_monitor_okx/static/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/docs/shortcut-icon.md b/docs/shortcut-icon.md index a6d380b..9e4ccfc 100644 --- a/docs/shortcut-icon.md +++ b/docs/shortcut-icon.md @@ -9,7 +9,7 @@ 3. `link rel="icon"` / `favicon.ico` 4. 若都没有 → 灰色地球或网页标题首字 -本仓库已在 **中控** 与 **四所监控页** 配置统一品牌图标(深色底 + 青绿渐变 K 线),与页面 UI 一致。 +本仓库已在 **中控** 与 **四所监控页** 配置统一品牌图标(深色圆角底 + 青绿趋势线 + 简化的 K 线),与页面 UI 一致。PNG/ICO 由 **Pillow** 生成,避免损坏的 favicon 出现花屏。 ## 文件位置 diff --git a/manual_trading_hub/static/icons/apple-touch-icon.png b/manual_trading_hub/static/icons/apple-touch-icon.png index b6b498f..bd835ad 100644 Binary files a/manual_trading_hub/static/icons/apple-touch-icon.png and b/manual_trading_hub/static/icons/apple-touch-icon.png differ diff --git a/manual_trading_hub/static/icons/favicon.ico b/manual_trading_hub/static/icons/favicon.ico index ee96d17..0af9b9c 100644 Binary files a/manual_trading_hub/static/icons/favicon.ico and b/manual_trading_hub/static/icons/favicon.ico differ diff --git a/manual_trading_hub/static/icons/icon-16.png b/manual_trading_hub/static/icons/icon-16.png index 2840450..b3a4ee1 100644 Binary files a/manual_trading_hub/static/icons/icon-16.png and b/manual_trading_hub/static/icons/icon-16.png differ diff --git a/manual_trading_hub/static/icons/icon-192.png b/manual_trading_hub/static/icons/icon-192.png index b0a9171..92351e1 100644 Binary files a/manual_trading_hub/static/icons/icon-192.png and b/manual_trading_hub/static/icons/icon-192.png differ diff --git a/manual_trading_hub/static/icons/icon-32.png b/manual_trading_hub/static/icons/icon-32.png index ef0c5cf..dc2186f 100644 Binary files a/manual_trading_hub/static/icons/icon-32.png and b/manual_trading_hub/static/icons/icon-32.png differ diff --git a/manual_trading_hub/static/icons/icon-512.png b/manual_trading_hub/static/icons/icon-512.png index 07604a6..a46fe93 100644 Binary files a/manual_trading_hub/static/icons/icon-512.png and b/manual_trading_hub/static/icons/icon-512.png differ diff --git a/manual_trading_hub/static/icons/icon.svg b/manual_trading_hub/static/icons/icon.svg index 3813302..2277788 100644 --- a/manual_trading_hub/static/icons/icon.svg +++ b/manual_trading_hub/static/icons/icon.svg @@ -1,31 +1,17 @@ - + - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + diff --git a/scripts/generate_brand_icons.py b/scripts/generate_brand_icons.py index f2df9fa..6db8ba3 100644 --- a/scripts/generate_brand_icons.py +++ b/scripts/generate_brand_icons.py @@ -1,212 +1,110 @@ #!/usr/bin/env python3 -"""从 brand/icon.svg 逻辑绘制 PNG/ICO,供 Chrome 快捷方式、PWA manifest 使用。""" +"""生成品牌 PNG/ICO(Pillow),供 Chrome 快捷方式与 manifest 使用。""" from __future__ import annotations import os -import struct -import zlib +import shutil REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) OUT = os.path.join(REPO, "brand", "icons") +BG = (12, 16, 25, 255) +PANEL = (20, 27, 45, 255) +CYAN = (34, 211, 238, 255) +GREEN = (52, 211, 153, 255) +RED = (248, 113, 113, 255) -def _png_chunk(tag: bytes, data: bytes) -> bytes: - return ( - struct.pack(">I", len(data)) - + tag - + data - + struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF) + +def _lerp(c1: tuple[int, ...], c2: tuple[int, ...], t: float) -> tuple[int, int, int, int]: + t = max(0.0, min(1.0, t)) + return tuple(int(c1[i] + (c2[i] - c1[i]) * t) for i in range(4)) # type: ignore + + +def _rounded_rect(draw, box, radius: int, fill) -> None: + draw.rounded_rectangle(box, radius=radius, fill=fill) + + +def render_icon(size: int): + from PIL import Image, ImageDraw + + img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) + draw = ImageDraw.Draw(img) + m = max(6, size // 12) + r = max(8, size // 6) + _rounded_rect(draw, (m, m, size - m, size - m), r, BG) + inner = m + max(2, size // 28) + _rounded_rect(draw, (inner, inner, size - inner, size - inner), max(6, r - 4), PANEL) + + # 渐变描边(四角采样) + border = max(2, size // 42) + for i in range(border): + t0 = i / max(1, border - 1) + for x in range(inner, size - inner): + t = (x - inner) / max(1, size - 2 * inner) + col = _lerp(CYAN, GREEN, (t + t0) * 0.5) + draw.point((x, inner + i), fill=col) + draw.point((x, size - inner - 1 - i), fill=col) + for y in range(inner, size - inner): + t = (y - inner) / max(1, size - 2 * inner) + col = _lerp(CYAN, GREEN, (t + t0) * 0.5) + draw.point((inner + i, y), fill=col) + draw.point((size - inner - 1 - i, y), fill=col) + + def sx(v: float) -> int: + return int(v * size / 512) + + def sy(v: float) -> int: + return int(v * size / 512) + + # 趋势线 + pts = [(120, 320), (200, 248), (280, 272), (392, 168)] + scaled = [(sx(x), sy(y)) for x, y in pts] + draw.line(scaled, fill=CYAN, width=max(2, size // 26), joint="curve") + ex, ey = scaled[-1] + draw.ellipse( + (ex - size // 28, ey - size // 28, ex + size // 28, ey + size // 28), + fill=GREEN, ) - -def _write_png(path: str, size: int, rgba: bytes) -> None: - raw = b"" - stride = size * 4 - for y in range(size): - raw += b"\x00" + rgba[y * stride : (y + 1) * stride] - ihdr = struct.pack(">IIBBBBB", size, size, 8, 6, 0, 0, 0) - idat = zlib.compress(raw, 9) - png = ( - b"\x89PNG\r\n\x1a\n" - + _png_chunk(b"IHDR", ihdr) - + _png_chunk(b"IDAT", idat) - + _png_chunk(b"IEND", b"") - ) - with open(path, "wb") as f: - f.write(png) - - -def _lerp(a: float, b: float, t: float) -> float: - return a + (b - a) * t - - -def _gradient(t: float) -> tuple[int, int, int]: - if t < 0.55: - u = t / 0.55 - return ( - int(_lerp(0, 0, u)), - int(_lerp(212, 139, u)), - int(_lerp(255, 255, u)), + # 蜡烛 + def candle(cx, top, bottom, body_top, body_bottom, color): + w = max(1, size // 64) + bh = max(2, size // 32) + draw.line((cx, top, cx, bottom), fill=color, width=w) + draw.rounded_rectangle( + (cx - bh, body_top, cx + bh, body_bottom), + radius=max(1, bh // 3), + fill=color, ) - u = (t - 0.55) / 0.45 - return ( - int(_lerp(61, 0, u)), - int(_lerp(255, 255, u)), - int(_lerp(157, 157, u)), - ) + candle(sx(182), sy(248), sy(340), sy(268), sy(332), RED) + candle(sx(282), sy(200), sy(340), sy(220), sy(316), GREEN) -def _inside_round_rect(x: int, y: int, size: int, pad: int, radius: int) -> bool: - if x < pad or y < pad or x >= size - pad or y >= size - pad: - return False - r = radius - if x < pad + r and y < pad + r: - return (x - pad - r) ** 2 + (y - pad - r) ** 2 <= r * r - if x >= size - pad - r and y < pad + r: - return (x - (size - pad - r)) ** 2 + (y - pad - r) ** 2 <= r * r - if x < pad + r and y >= size - pad - r: - return (x - pad - r) ** 2 + (y - (size - pad - r)) ** 2 <= r * r - if x >= size - pad - r and y >= size - pad - r: - return (x - (size - pad - r)) ** 2 + (y - (size - pad - r)) ** 2 <= r * r - return True - - -def _draw_candle( - buf: bytearray, - size: int, - cx: int, - top: int, - bottom: int, - body_top: int, - body_bottom: int, - rgb: tuple[int, int, int], - wick_w: int = 2, - body_half: int = 7, -) -> None: - for y in range(max(0, top), min(size, bottom + 1)): - for x in range(cx - wick_w, cx + wick_w + 1): - if 0 <= x < size: - i = (y * size + x) * 4 - buf[i : i + 3] = bytes((*rgb, 255)) - for y in range(max(0, body_top), min(size, body_bottom + 1)): - for x in range(cx - body_half, cx + body_half + 1): - if 0 <= x < size: - i = (y * size + x) * 4 - buf[i : i + 3] = bytes((*rgb, 255)) - - -def render_icon_rgba(size: int) -> bytes: - buf = bytearray(size * size * 4) - pad = max(4, size // 14) - radius = size // 5 - inner_pad = pad + max(2, size // 32) - ring_w = max(2, size // 48) - - for y in range(size): - for x in range(size): - i = (y * size + x) * 4 - if not _inside_round_rect(x, y, size, pad, radius): - buf[i : i + 4] = b"\x00\x00\x00\x00" - continue - if _inside_round_rect(x, y, size, inner_pad, radius - 4): - buf[i : i + 4] = bytes((18, 24, 42, 255)) - else: - t = (x + y) / (2 * size) - r, g, b = _gradient(t) - buf[i : i + 4] = bytes((r, g, b, 220)) - - s = size / 512.0 - def sc(v: int) -> int: - return int(v * s) - - _draw_candle(buf, size, sc(148), sc(228), sc(332), sc(252), sc(304), (255, 77, 109), sc(8), sc(16)) - _draw_candle(buf, size, sc(228), sc(196), sc(352), sc(220), sc(308), (0, 255, 157), sc(8), sc(16)) - _draw_candle(buf, size, sc(308), sc(240), sc(320), sc(264), sc(304), (0, 255, 157), sc(8), sc(14)) - _draw_candle(buf, size, sc(384), sc(180), sc(300), sc(208), sc(272), (0, 255, 157), sc(8), sc(16)) - - ccx, ccy = sc(256), sc(256) - cr = sc(52) - for y in range(size): - for x in range(size): - d = ((x - ccx) ** 2 + (y - ccy) ** 2) ** 0.5 - if cr - ring_w <= d <= cr: - t = (x + y) / (2 * size) - r, g, b = _gradient(t) - i = (y * size + x) * 4 - buf[i : i + 4] = bytes((r, g, b, 200)) - tri = [ - (sc(236), sc(276)), - (sc(256), sc(220)), - (sc(276), sc(276)), - ] - - def _in_tri(px: int, py: int) -> bool: - x1, y1 = tri[0] - x2, y2 = tri[1] - x3, y3 = tri[2] - d1 = (px - x2) * (y1 - y2) - (x1 - x2) * (py - y2) - d2 = (px - x3) * (y2 - y3) - (x2 - x3) * (py - y3) - d3 = (px - x1) * (y3 - y1) - (x3 - x1) * (py - y1) - has_neg = d1 < 0 or d2 < 0 or d3 < 0 - has_pos = d1 > 0 or d2 > 0 or d3 > 0 - return not (has_neg and has_pos) - - for y in range(size): - for x in range(size): - if _in_tri(x, y): - t = (x + y) / (2 * size) - r, g, b = _gradient(t) - i = (y * size + x) * 4 - buf[i : i + 4] = bytes((r, g, b, 255)) - return bytes(buf) - - -def _write_ico(path: str, sizes: list[int]) -> None: - images = [] - for sz in sizes: - rgba = render_icon_rgba(sz) - # BGRA bottom-up for ICO - row = sz * 4 - pixels = bytearray() - for y in range(sz - 1, -1, -1): - for x in range(sz): - i = (y * sz + x) * 4 - pixels.extend([rgba[i + 2], rgba[i + 1], rgba[i], rgba[i + 3]]) - and_row = (sz * 4 + 3) & ~3 - if and_row > sz * 4: - pixels.extend(b"\x00" * (and_row - sz * 4)) - bmp = b"BM" + struct.pack(" None: - os.makedirs(OUT, exist_ok=True) - import shutil + from PIL import Image - shutil.copy2( - os.path.join(REPO, "brand", "icon.svg"), - os.path.join(OUT, "icon.svg"), + os.makedirs(OUT, exist_ok=True) + shutil.copy2(os.path.join(REPO, "brand", "icon.svg"), os.path.join(OUT, "icon.svg")) + + sizes = [16, 32, 48, 180, 192, 512] + images: dict[int, Image.Image] = {} + for sz in sizes: + im = render_icon(sz) + images[sz] = im + name = "apple-touch-icon.png" if sz == 180 else f"icon-{sz}.png" + im.save(os.path.join(OUT, name), format="PNG", optimize=True) + + ico_sizes = [16, 32, 48] + ico_imgs = [images[s] for s in ico_sizes] + ico_imgs[0].save( + os.path.join(OUT, "favicon.ico"), + format="ICO", + sizes=[(s, s) for s in ico_sizes], + append_images=ico_imgs[1:], ) - for sz in (16, 32, 180, 192, 512): - _write_png(os.path.join(OUT, f"icon-{sz}.png"), sz, render_icon_rgba(sz)) - shutil.copy2(os.path.join(OUT, "icon-180.png"), os.path.join(OUT, "apple-touch-icon.png")) - _write_ico(os.path.join(OUT, "favicon.ico"), [16, 32, 48]) print(f"DONE {OUT}")