K1Guitar/tools/gen_ui0902_previews.py

140 lines
5.7 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Generate page previews mimicking the firmware layout with 0902 assets."""
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
SRC = ROOT / "tools" / "assets_0902"
OUT = ROOT / "tools" / "out"
MISANS = r"c:\Users\qjyu\Documents\SoundWalker\一诺国际吉他\Doc\UI\MiSans\MiSans 字体\MiSans-Medium.ttf"
PAGE_BG = (0, 8, 19)
ROW_BG = (36, 43, 58)
DIVIDER = (41, 48, 62)
def load(rel):
return Image.open(SRC / rel).convert("RGBA")
def paste_trans(page, im, x, y):
page.paste(im, (x, y), im)
def draw_status_bar(page, d, bt_on=True, pct=75, vol=3):
d.rectangle([0, 0, 239, 25], fill=PAGE_BG)
paste_trans(page, load("02_顶部图标/音量图标-10.png"), 8, 6)
if bt_on:
paste_trans(page, load("02_顶部图标/蓝牙图标-10.png"), 36, 5)
# volume level bars x=55.., 5 bars
for i in range(5):
h = 4 + i * 2
c = (255, 255, 255) if i < vol else (90, 96, 104)
d.rectangle([55 + i * 5, 21 - h, 55 + i * 5 + 2, 21], fill=c)
# battery
outline = load("02_顶部图标/电池图标-10.png").copy()
px = outline.load()
for yy in range(2, 10):
for xx in range(2, 27):
px[xx, yy] = (0, 0, 0, 0)
fill = load("02_顶部图标/电池电量-10-11.png")
fw = int(22 * pct / 100)
if fw > 0:
paste_trans(page, fill.crop((0, 0, fw, 9)), 206, 9)
paste_trans(page, outline, 203, 7)
d.line([0, 26, 239, 26], fill=DIVIDER)
def draw_bottom_bar(page, d, sel=None, back=False):
d.rectangle([0, 275, 239, 319], fill=PAGE_BG)
if back:
first = load("03_底部图标/底部图标-17.png") # back not-sel
else:
first = load("03_底部图标/底部图标-11.png") if sel != 0 else load("03_底部图标/底部图标-10.png")
second = load("03_底部图标/底部图标-12.png") if sel == 1 else load("03_底部图标/底部图标-13.png")
third = load("03_底部图标/底部图标-14.png") if sel == 2 else load("03_底部图标/底部图标-15.png")
for im, cx in ((first, 40), (second, 120), (third, 200)):
paste_trans(page, im, cx - im.width // 2, 288)
def new_page():
im = Image.new("RGB", (240, 320), PAGE_BG)
return im, ImageDraw.Draw(im)
def text_center(d, cx, y, s, size, color=(255, 255, 255)):
f = ImageFont.truetype(MISANS, size)
bb = d.textbbox((0, 0), s, font=f)
d.text((cx - (bb[2] - bb[0]) / 2 - bb[0], y), s, fill=color, font=f)
# ---------- 1. mode select ----------
p, d = new_page()
draw_status_bar(p, d)
rows = [("04_模式图标/完整版/模式界面栏背景-17.png", 30),
("04_模式图标/完整版/模式界面栏背景-18.png", 116),
("04_模式图标/完整版/模式界面栏背景-20.png", 202)]
for rel, y in rows:
paste_trans(p, load(rel).resize((222, 84), Image.LANCZOS), 9, y)
draw_bottom_bar(p, d, sel=2)
p.save(OUT / "preview_01_mode_select.png")
# ---------- 2. mixer ----------
p, d = new_page()
draw_status_bar(p, d)
text_center(d, 120, 6, "调音台", 16)
track = load("06_控件/调音台控件/调音台控件-3.png")
knob = load("06_控件/调音台控件/调音台控件-1.png")
labels = ["06_控件/调音台控件/文字/调音台文字-13.png", # MIC
"06_控件/调音台控件/文字/调音台文字-14.png", # 吉他
"06_控件/调音台控件/文字/调音台文字-15.png", # 伴奏
"06_控件/调音台控件/文字/调音台文字-16.png"] # 人声效果
vals = [7, 7, 7, 7]
for i, cx in enumerate((30, 90, 150, 210)):
paste_trans(p, track, cx - 15, 35)
ky = 35 + int((10 - vals[i]) / 10 * (215 - 24))
paste_trans(p, knob, cx - 15, ky)
text_center(d, cx, ky + 5, str(vals[i]), 11, color=(20, 25, 35))
lab = load(labels[i])
paste_trans(p, lab, cx - lab.width // 2, 258)
draw_bottom_bar(p, d, sel=1)
p.save(OUT / "preview_05_mixer.png")
# ---------- 3. settings ----------
p, d = new_page()
draw_status_bar(p, d)
text_center(d, 120, 6, "设置", 16)
rows_cfg = [
("05_设置图标/设置图标-01.png", "蓝牙设置", ""),
("05_设置图标/设置图标-02.png", "自动关机", "15分钟"),
("06_控件/系统设置/系统设置图标-11.png", "恢复出厂设置", None),
("06_控件/系统设置/系统设置图标-13.png", "版本信息", "0.1.11"),
]
chev = load("05_设置图标/设置图标-03.png")
for i, (icon, label, val) in enumerate(rows_cfg):
y = 42 + i * 46
d.rounded_rectangle([13, y, 226, y + 32], radius=8, fill=ROW_BG)
ic = load(icon)
paste_trans(p, ic, 20, y + (33 - ic.height) // 2)
f = ImageFont.truetype(MISANS, 13)
d.text((62, y + 9), label, fill=(255, 255, 255), font=f)
if val:
fv = ImageFont.truetype(MISANS, 11)
bb = d.textbbox((0, 0), val, font=fv)
d.text((200 - (bb[2] - bb[0]), y + 11), val, fill=(150, 156, 165), font=fv)
paste_trans(p, chev, 212, y + 7)
draw_bottom_bar(p, d, back=True)
p.save(OUT / "preview_06_settings.png")
# ---------- 4. restore dialog ----------
p, d = new_page()
draw_status_bar(p, d)
text_center(d, 120, 6, "恢复出厂设置", 16)
text_center(d, 120, 120, "确认恢复出厂设置,恢复后所有设置将", 12)
text_center(d, 120, 142, "清除并重启。", 12)
paste_trans(p, load("06_控件/控件-10.png"), 13, 185)
# derived cancel button
im = Image.new("RGBA", (106, 56), (0, 0, 0, 0))
dd = ImageDraw.Draw(im)
dd.rounded_rectangle([0, 0, 105, 55], radius=12, fill=ROW_BG + (255,))
f24 = ImageFont.truetype(MISANS, 24)
bb = dd.textbbox((0, 0), "取消", font=f24)
dd.text(((106 - (bb[2] - bb[0])) // 2 - bb[0], (56 - (bb[3] - bb[1])) // 2 - bb[1]), "取消", fill=(255, 255, 255), font=f24)
paste_trans(p, im, 121, 185)
draw_bottom_bar(p, d, back=True)
p.save(OUT / "preview_07_restore.png")
print("previews saved")