feat: 沙香科技官网 v2.2 基线(深色科技风/双语/局域网+公网双部署)

This commit is contained in:
dafe
2026-11-02 14:57:08 +08:00
commit 924bca9f98
91 changed files with 1632 additions and 0 deletions

71
tools/make_logo_light.py Normal file
View File

@@ -0,0 +1,71 @@
# -*- coding: utf-8 -*-
"""
生成深色站反白版 logo(logo-light.png):
1. flood-fill 镂空深蓝底(容差 84 = v1 验证成功参数,能吃掉 #000020 底色)
2. 不透明内容亮度反转 L' = 1 - L(黑字→白字,红/青/绿提亮,色相保留)
深色页黑字看不清、白底块又突兀,反白是深色站标准解法。
用法: uv run --with pillow python3 tools/make_logo_light.py
"""
import colorsys
from collections import deque
from PIL import Image
SRC = 'assets/img/logo.png'
OUT = 'assets/img/logo-light.png'
TOL = 84 # 曼哈顿距离容差(v1 实测:清除 83%、红色主体完整保留)
im = Image.open(SRC).convert('RGBA')
w, h = im.size
px = im.load()
# --- flood-fill 清底 ---
corners = [px[0, 0], px[w-1, 0], px[0, h-1], px[w-1, h-1]]
bg = tuple(sum(c[i] for c in corners) // 4 for i in range(3))
def is_bg(p):
if p[3] < 10:
return True
return abs(p[0]-bg[0]) + abs(p[1]-bg[1]) + abs(p[2]-bg[2]) <= TOL
seen = [[False]*w for _ in range(h)]
q = deque()
for x in range(w):
q.extend(((x, 0), (x, h-1)))
for y in range(h):
q.extend(((0, y), (w-1, y)))
cleared = 0
while q:
x, y = q.popleft()
if x < 0 or x >= w or y < 0 or y >= h or seen[y][x]:
continue
seen[y][x] = True
p = px[x, y]
if not is_bg(p):
continue
px[x, y] = (0, 0, 0, 0)
cleared += 1
q.extend(((x+1, y), (x-1, y), (x, y+1), (x, y-1)))
ratio = cleared / (w * h)
assert 0.10 < ratio < 0.92, f'镂空异常: 清除 {ratio:.0%}'
# --- 暗部提亮、亮部保留(logo 含 ~20% 浅色元素,全量反转会把它们变黑) ---
# L' = max(L, 1-L):暗像素翻到亮侧(黑→白),亮像素不动,色相全保留
opaque = [px[x, y] for y in range(h) for x in range(w) if px[x, y][3] > 128]
assert opaque, '镂空后内容为空'
for y in range(h):
for x in range(w):
r, g, b, a = px[x, y]
if a == 0:
continue
hh, ll, ss = colorsys.rgb_to_hls(r / 255, g / 255, b / 255)
r2, g2, b2 = colorsys.hls_to_rgb(hh, max(ll, 1 - ll), ss)
px[x, y] = (round(r2 * 255), round(g2 * 255), round(b2 * 255), a)
im.save(OUT, 'PNG', optimize=True)
# 验证:反白后所有不透明像素亮度下限
final = [px[x, y] for y in range(h) for x in range(w) if px[x, y][3] > 128]
dark = sum(1 for p in final if 0.299*p[0]+0.587*p[1]+0.114*p[2] < 90) / len(final)
print(f'完成: {OUT} 镂空 {ratio:.0%},暗部像素剩 {dark:.1%}(应为 0)')