- Подложка adaptive-иконки: градиент под акцент темы + радиальное свечение + мягкая тень от логотипа (ic_bg_<тема>, было плоским цветом). Иконку-лого не трогал. - Сплэш под выбранную тему: системный сплэш Android 12+ нельзя перекрасить под выбор пользователя (alias-тема на ColorOS игнорится), поэтому системный = просто тёмный (splash_transparent), а красивый сплэш рисуем сами на Compose (SplashOverlay): 3D-лого + акцентное свечение + тень + анимация, цвет берём из текущей темы. - Тему на старте читаем синхронно из SharedPreferences (мгновенно, без блокировки кадра). - Ускорен холодный старт до первого кадра 1.48с→1.11с: сплэш рисуется на первом дешёвом кадре, тяжёлый контент (ViewModels/плеер) композится под ним; старт PlayerService уведён с критического пути. Остаток — оверхед debug-сборки.
74 lines
3.4 KiB
Python
74 lines
3.4 KiB
Python
# -*- 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)
|