feat(splash+icon): фон иконки-градиент под тему + темо-зависимый сплэш
- Подложка adaptive-иконки: градиент под акцент темы + радиальное свечение + мягкая тень от логотипа (ic_bg_<тема>, было плоским цветом). Иконку-лого не трогал. - Сплэш под выбранную тему: системный сплэш Android 12+ нельзя перекрасить под выбор пользователя (alias-тема на ColorOS игнорится), поэтому системный = просто тёмный (splash_transparent), а красивый сплэш рисуем сами на Compose (SplashOverlay): 3D-лого + акцентное свечение + тень + анимация, цвет берём из текущей темы. - Тему на старте читаем синхронно из SharedPreferences (мгновенно, без блокировки кадра). - Ускорен холодный старт до первого кадра 1.48с→1.11с: сплэш рисуется на первом дешёвом кадре, тяжёлый контент (ViewModels/плеер) композится под ним; старт PlayerService уведён с критического пути. Остаток — оверхед debug-сборки.
This commit is contained in:
73
design/logos/gen_bg.py
Normal file
73
design/logos/gen_bg.py
Normal file
@@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Фоны adaptive-иконки: градиент под акцент темы + радиальное свечение + тень от логотипа."""
|
||||
from PIL import Image, ImageDraw, ImageFilter
|
||||
import numpy as np, os
|
||||
|
||||
TH = r"C:\radiOLA\design\logos\gen\themed"
|
||||
DRW = r"C:\radiOLA\app\src\main\res\drawable-nodpi"
|
||||
PREV = os.environ["LOCALAPPDATA"] + r"\Temp\radiola_bg_preview.png"
|
||||
S = 432
|
||||
THEMES = [
|
||||
("forest", (0xA8,0xE0,0x5F), (0x0C,0x14,0x10)),
|
||||
("ocean", (0x4F,0xD6,0xE0), (0x0A,0x0F,0x1A)),
|
||||
("sunset", (0xFF,0x8A,0x5B), (0x1A,0x0F,0x0C)),
|
||||
("amethyst",(0xB3,0x88,0xFF), (0x12,0x0E,0x1A)),
|
||||
("neon", (0xFF,0x4D,0x9D), (0x0D,0x0A,0x12)),
|
||||
("amber", (0xFF,0xC2,0x47), (0x14,0x11,0x0A)),
|
||||
("ice", (0x7F,0xB3,0xFF), (0x0C,0x10,0x14)),
|
||||
("rose", (0xFF,0x7E,0xA8), (0x16,0x0E,0x12)),
|
||||
]
|
||||
|
||||
def lerp(a,b,t): return tuple(a[i]+(b[i]-a[i])*t for i in range(3))
|
||||
|
||||
yy,xx = np.mgrid[0:S,0:S]
|
||||
cx,cy=S*0.5,S*0.46
|
||||
rad = np.sqrt((xx-cx)**2+(yy-cy)**2)/(S*0.62) # 0 в центре → ~1 к краю
|
||||
diag = (xx+yy)/(2*S) # 0 верх-лево → 1 низ-право
|
||||
|
||||
def make_bg(accent, bg):
|
||||
acc=np.array(accent,float); base=np.array(bg,float)
|
||||
# 1) база: лёгкий диагональный градиент (верх чуть светлее с оттенком акцента, низ темнее)
|
||||
top = lerp(bg, accent, 0.10); top=np.array([min(255,c*1.15) for c in top])
|
||||
bot = np.array([c*0.7 for c in bg])
|
||||
g = diag[...,None]
|
||||
img = top*(1-g) + bot*g
|
||||
# 2) радиальное акцентное свечение в центре
|
||||
glow = np.clip(1-rad,0,1)**1.7
|
||||
img = img + (acc-img)*(glow[...,None]*0.30)
|
||||
# 3) виньетка по углам
|
||||
vig = np.clip(rad-0.6,0,1)
|
||||
img = img*(1-vig[...,None]*0.35)
|
||||
return Image.fromarray(np.clip(img,0,255).astype("uint8"),"RGB").convert("RGBA")
|
||||
|
||||
def r_shadow(theme):
|
||||
"""Мягкая тень от логотипа (силуэт R), запечённая в фон."""
|
||||
logo=Image.open(os.path.join(TH,f"logo_{theme}.png")).convert("RGBA")
|
||||
logo=logo.crop(logo.getbbox())
|
||||
target=196; sc=target/max(logo.size)
|
||||
logo=logo.resize((int(logo.width*sc),int(logo.height*sc)))
|
||||
sh=Image.new("RGBA",(S,S),(0,0,0,0))
|
||||
# силуэт из альфы
|
||||
sil=Image.new("RGBA",(S,S),(0,0,0,0))
|
||||
a=logo.split()[3]
|
||||
blk=Image.new("RGBA",logo.size,(0,0,0,150))
|
||||
sil.paste(blk,((S-logo.width)//2+7,(S-logo.height)//2+14),a) # сдвиг вниз-вправо
|
||||
sil=sil.filter(ImageFilter.GaussianBlur(16))
|
||||
return sil
|
||||
|
||||
cols=4; rows=2; pad=16
|
||||
sheet=Image.new("RGB",(cols*S//2+(cols+1)*pad, rows*S//2+(rows+1)*pad),(28,28,32))
|
||||
for i,(name,acc,bg) in enumerate(THEMES):
|
||||
base=make_bg(acc,bg)
|
||||
base.alpha_composite(r_shadow(name))
|
||||
base.convert("RGB").save(os.path.join(DRW,f"ic_bg_{name}.png"))
|
||||
# превью: фон + foreground + круглая маска
|
||||
fg=Image.open(os.path.join(DRW,f"ic_fg_{name}.png")).convert("RGBA")
|
||||
full=base.copy(); full.alpha_composite(fg)
|
||||
mask=Image.new("L",(S,S),0); ImageDraw.Draw(mask).ellipse([0,0,S,S],fill=255)
|
||||
out=Image.new("RGB",(S,S),(28,28,32)); out.paste(full.convert("RGB"),(0,0),mask)
|
||||
out=out.resize((S//2,S//2))
|
||||
r=i//cols; c=i%cols; x=pad+c*(S//2+pad); y=pad+r*(S//2+pad)
|
||||
sheet.paste(out,(x,y))
|
||||
sheet.save(PREV)
|
||||
print("bg generated + preview", PREV)
|
||||
Reference in New Issue
Block a user