chore: 文件夹更名 HDMI-Tool -> DLPilot(路径与文档此前已对齐)

This commit is contained in:
2026-09-14 15:25:05 +08:00
parent f0f8073afc
commit a6721415a6
57 changed files with 0 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
生成 640x360 黑白测试图, 供 HDMI 源端工具的自定义栏位使用
================================================================
输出到 ../assets/(仓库资产目录, 发布打包时随 zip 分发); 预置栏位配置
release/pattern_slots.json 指向前 3 张, 其余两张可用 "" 换上。
图案清单(均为 640x360 黑白, 1:1 投屏无缩放):
bw_star.png 西门子星: 60 楔放射星, 看极限分辨率与中心偏移
bw_sweep.png 频率扫描条纹: 周期 24px 渐减到 3px(上竖线/下横线)
bw_checker_sweep.png 渐变棋盘: 格子尺寸 2px 递增到 32px 共 9 段
bw_zoneplate.png 同心波带片: 环距向中心递减, 看各向混叠
bw_testcard.png 综合测试卡: 灰阶/刻度/细棋盘/粗细线/标记
用法: python gen_bw_patterns.py
"""
import math
import os
from PIL import Image, ImageDraw
W, H = 640, 360
SRC = os.path.dirname(os.path.abspath(__file__))
OUT = os.path.join(os.path.dirname(SRC), 'assets')
def save(img, name):
os.makedirs(OUT, exist_ok=True)
path = os.path.join(OUT, name)
img.save(path)
print(f'写出 {path}')
def gen_star():
"""西门子星: 60 个黑白交替楔形, 边缘楔宽约 17px, 向中心无限加密"""
img = Image.new('L', (W, H), 255)
d = ImageDraw.Draw(img)
cx, cy, R = W // 2, H // 2, 165
n = 60
for i in range(0, n, 2): # 黑楔在偶数位, 底为白
d.pieslice([cx - R, cy - R, cx + R, cy + R],
i * 360.0 / n, (i + 1) * 360.0 / n, fill=0)
d.ellipse([cx - R - 6, cy - R - 6, cx + R + 6, cy + R + 6],
outline=0, width=3)
d.rectangle([0, 0, W - 1, H - 1], outline=0, width=2)
save(img, 'bw_star.png')
def gen_sweep():
"""频率扫描条纹: 左到右黑白条纹周期 24px 渐减到 3px; 上半竖线, 下半横线"""
img = Image.new('L', (W, H), 255)
px = img.load()
# 上半: 竖条纹
ph = 0.0
for x in range(W):
t = x / (W - 1)
ph += 1.0 / (24 - 21 * t)
if (ph % 1.0) < 0.5:
for y in range(H // 2):
px[x, y] = 0
# 下半: 横条纹
ph = 0.0
for y in range(H // 2, H):
t = (y - H // 2) / (H // 2 - 1)
ph += 1.0 / (24 - 21 * t)
if (ph % 1.0) < 0.5:
for x in range(W):
px[x, y] = 0
d = ImageDraw.Draw(img)
d.line([0, H // 2, W, H // 2], fill=0, width=2)
d.rectangle([0, 0, W - 1, H - 1], outline=0, width=2)
d.text((8, 6), 'H sweep 24px->3px', fill=0)
d.text((8, H // 2 + 6), 'V sweep 24px->3px', fill=0)
save(img, 'bw_sweep.png')
def gen_checker_sweep():
"""渐变棋盘: 格子尺寸从 2px 逐段加倍到 32px, 看多大格子开始可分辨"""
img = Image.new('L', (W, H), 0)
d = ImageDraw.Draw(img)
sizes = [2, 3, 4, 6, 8, 12, 16, 24, 32]
seg = W / len(sizes)
for i, s in enumerate(sizes):
x0, x1 = int(round(i * seg)), int(round((i + 1) * seg))
for yy in range(0, H, s):
for xx in range(x0, x1, s):
if ((xx // s) + (yy // s)) % 2 == 0:
d.rectangle([xx, yy, min(xx + s, x1) - 1, min(yy + s, H) - 1],
fill=255)
d.line([x1, 0, x1, H], fill=255, width=2)
d.text((4, 4), 'checker 2..32px', fill=255)
save(img, 'bw_checker_sweep.png')
def gen_zoneplate():
"""同心波带片: 环距中心处约 31px、边缘约 3.5px, 观察各方向混叠"""
img = Image.new('L', (W, H), 255)
px = img.load()
cx, cy, k = W / 2, H / 2, 0.0008
for y in range(H):
dy = y - cy
for x in range(W):
dx = x - cx
if math.cos(k * (dx * dx + dy * dy)) > 0:
px[x, y] = 0
d = ImageDraw.Draw(img)
d.rectangle([0, 0, W - 1, H - 1], outline=0, width=2)
save(img, 'bw_zoneplate.png')
def gen_testcard():
"""综合测试卡: 灰阶条 + 刻度 + 细棋盘 + 粗细线 + 角标"""
img = Image.new('L', (W, H), 0)
d = ImageDraw.Draw(img)
# 外框与 40px 刻度(边缘短刻线)
d.rectangle([0, 0, W - 1, H - 1], outline=255, width=2)
for x in range(40, W, 40):
d.line([x, 0, x, 10], fill=255, width=1)
d.line([x, H, x, H - 10], fill=255, width=1)
for y in range(40, H, 40):
d.line([0, y, 10, y], fill=255, width=1)
d.line([W, y, W - 10, y], fill=255, width=1)
# 顶部 16 级灰阶条
gw = W // 16
for i in range(16):
v = round(i * 255 / 15)
d.rectangle([i * gw, 20, (i + 1) * gw - 1, 44], fill=v, outline=255)
# 左下: 1px 棋盘块 (640/4=160 宽 x 72 高)
bx, by, bs = 16, H - 96, 2
for yy in range(by, by + 72, bs):
for xx in range(bx, bx + 160, bs):
if ((xx // bs) + (yy // bs)) % 2 == 0:
d.rectangle([xx, yy, xx + bs - 1, yy + bs - 1], fill=255)
d.text((bx, by - 14), '2px checker', fill=255)
# 右下: 1/2/4px 白线组(横线), 看线条再现
lx = W - 210
for row, lw in enumerate((1, 2, 4)):
y0 = H - 100 + row * 26
for off in range(0, 13, lw * 2):
d.line([lx, y0 + off, lx + 190, y0 + off], fill=255, width=lw)
d.text((lx, H - 114), '1/2/4px lines', fill=255)
# 中心十字(1px)
cx, cy = W // 2, H // 2
d.line([cx, 60, cx, H - 60], fill=255, width=1)
d.line([W // 4, cy, W - W // 4, cy], fill=255, width=1)
# 四角 L 标记
m, L = 16, 28
for sx, sy in ((m, m), (W - 1 - m, m), (m, H - 1 - m), (W - 1 - m, H - 1 - m)):
dx = -1 if sx > cx else 1
dy = -1 if sy > cy else 1
d.line([sx, sy, sx + dx * L, sy], fill=255, width=2)
d.line([sx, sy, sx, sy + dy * L], fill=255, width=2)
d.text((W // 2 - 60, 52), '640x360 TEST', fill=255)
save(img, 'bw_testcard.png')
if __name__ == '__main__':
gen_star()
gen_sweep()
gen_checker_sweep()
gen_zoneplate()
gen_testcard()