Files
pqAutomationApp/app/data_range_converter.py

279 lines
8.5 KiB
Python
Raw Normal View History

2026-04-16 16:51:05 +08:00
# -*- coding: UTF-8 -*-
"""
数据范围转换器
Full Range (065535) 转换为 Limited RangeSolidColor 刻度
2026-04-16 16:51:05 +08:00
"""
from app.solid_color_scale import (
LIMITED_SOLID_COLOR_BLACK,
LIMITED_SOLID_COLOR_WHITE,
SOLID_COLOR_MAX,
SOLID_COLOR_MIN,
clamp_solid_color,
)
2026-04-16 16:51:05 +08:00
class DataRangeConverter:
"""数据范围转换器"""
def __init__(self, verbose=True):
"""
初始化转换器
Args:
verbose: 是否打印详细日志
"""
self.verbose = verbose
def convert_value(self, value):
"""
将单个 Full Range 值转换为 Limited RangeSolidColor 刻度
2026-04-16 16:51:05 +08:00
转换公式归一化后线性映射:
limited = L_black + (value / MAX) × (L_white - L_black)
2026-04-16 16:51:05 +08:00
"""
value = clamp_solid_color(value)
if value <= SOLID_COLOR_MIN:
return LIMITED_SOLID_COLOR_BLACK
if value >= SOLID_COLOR_MAX:
return LIMITED_SOLID_COLOR_WHITE
span = LIMITED_SOLID_COLOR_WHITE - LIMITED_SOLID_COLOR_BLACK
limited = LIMITED_SOLID_COLOR_BLACK + round((value / SOLID_COLOR_MAX) * span)
return max(LIMITED_SOLID_COLOR_BLACK, min(LIMITED_SOLID_COLOR_WHITE, limited))
2026-04-16 16:51:05 +08:00
def convert_rgb(self, r, g, b):
"""转换单个 RGB 值SolidColor Full → Limited"""
2026-04-16 16:51:05 +08:00
return (self.convert_value(r), self.convert_value(g), self.convert_value(b))
def convert(self, pattern_params, data_range="Full"):
"""
转换图案参数列表
Args:
pattern_params: 图案参数列表 [[r,g,b], [r,g,b], ...]
data_range: "Full" "Limited"
Returns:
list: 转换后的图案参数列表
"""
# Full Range 不需要转换
if data_range == "Full":
if self.verbose:
print(f"使用 Full Range (0{SOLID_COLOR_MAX}),无需转换")
2026-04-16 16:51:05 +08:00
return pattern_params
# Limited Range 需要转换
if data_range == "Limited":
if self.verbose:
self._print_header()
converted = []
for i, rgb in enumerate(pattern_params):
# 获取原始值
r_orig, g_orig, b_orig = rgb[0], rgb[1], rgb[2]
# 转换
r_new, g_new, b_new = self.convert_rgb(r_orig, g_orig, b_orig)
# 保存
converted.append([r_new, g_new, b_new])
# 打印日志(关键值)
if self.verbose:
self._print_conversion(
i, r_orig, g_orig, b_orig, r_new, g_new, b_new
)
if self.verbose:
self._print_footer(len(pattern_params))
return converted
# 未知范围,返回原始值
else:
if self.verbose:
print(f"⚠ 未知的数据范围: {data_range},使用原始值")
return pattern_params
def _print_header(self):
"""打印转换头部信息"""
print("=" * 80)
print("【数据范围转换】Limited Range (SolidColor 刻度)")
print(
f" 映射: {SOLID_COLOR_MIN}{SOLID_COLOR_MAX}"
f"{LIMITED_SOLID_COLOR_BLACK}{LIMITED_SOLID_COLOR_WHITE}"
)
2026-04-16 16:51:05 +08:00
print("=" * 80)
def _print_conversion(self, index, r_orig, g_orig, b_orig, r_new, g_new, b_new):
"""
打印转换日志
策略只打印关键值避免刷屏
- 第一个和最后一个图案
- 0, 128, 255 等关键值
"""
# 判断是否需要打印
should_print = False
label = ""
mid = SOLID_COLOR_MAX // 2
2026-04-16 16:51:05 +08:00
if index == 0:
should_print = True
label = "黑色"
elif index == len([]) - 1: # 需要在外部判断
should_print = True
label = "白色"
elif (
r_orig in [SOLID_COLOR_MIN, mid, SOLID_COLOR_MAX]
or g_orig in [SOLID_COLOR_MIN, mid, SOLID_COLOR_MAX]
or b_orig in [SOLID_COLOR_MIN, mid, SOLID_COLOR_MAX]
2026-04-16 16:51:05 +08:00
):
should_print = True
if r_orig == mid:
2026-04-16 16:51:05 +08:00
label = "50%"
if should_print:
diff = abs(r_new - r_orig)
print(
f" 图案 {index+1:2d} {label:8s}: "
f"RGB({r_orig:3d},{g_orig:3d},{b_orig:3d}) → "
f"RGB({r_new:3d},{g_new:3d},{b_new:3d}) "
f"(差值: {diff:+3d})"
)
def _print_footer(self, total_count):
"""打印转换尾部信息"""
2026-04-21 15:31:48 +08:00
print(f"转换完成,共 {total_count} 个图案")
2026-04-16 16:51:05 +08:00
print("=" * 80)
def get_info(self):
"""获取转换器信息"""
return {
"name": "Data Range Converter",
"version": "1.0.0",
"full_range": f"0-{SOLID_COLOR_MAX}",
"limited_range": f"{LIMITED_SOLID_COLOR_BLACK}-{LIMITED_SOLID_COLOR_WHITE}",
"formula": "L_black + (value / MAX) × (L_white - L_black)",
2026-04-16 16:51:05 +08:00
}
# ========== 便捷函数 ==========
def convert_pattern_params(pattern_params, data_range="Full", verbose=True):
"""
便捷函数转换图案参数
Args:
pattern_params: 图案参数列表 [[r,g,b], [r,g,b], ...]
data_range: "Full" "Limited"
verbose: 是否打印日志
Returns:
list: 转换后的图案参数列表
示例:
2026-04-20 11:48:38 +08:00
>>> from app.data_range_converter import convert_pattern_params
>>> params = [[0,0,0], [65535,65535,65535]]
2026-04-16 16:51:05 +08:00
>>> converted = convert_pattern_params(params, "Limited")
[[4112,4112,4112], [60492,60492,60492]]
2026-04-16 16:51:05 +08:00
"""
converter = DataRangeConverter(verbose=verbose)
return converter.convert(pattern_params, data_range)
def convert_single_rgb(r, g, b, data_range="Full"):
"""
便捷函数转换单个 RGB
Args:
r, g, b: RGB (065535)
2026-04-16 16:51:05 +08:00
data_range: "Full" "Limited"
Returns:
tuple: 转换后的 RGB
示例:
2026-04-20 11:48:38 +08:00
>>> from app.data_range_converter import convert_single_rgb
2026-04-16 16:51:05 +08:00
>>> r, g, b = convert_single_rgb(0, 0, 0, "Limited")
(16, 16, 16)
"""
if data_range == "Full":
return (r, g, b)
converter = DataRangeConverter(verbose=False)
return converter.convert_rgb(r, g, b)
# ========== 测试代码 ==========
if __name__ == "__main__":
"""测试转换器"""
print("=" * 80)
print("数据范围转换器 - 测试")
print("=" * 80)
# 测试 1: 基本转换
print("\n[测试 1] 基本转换...")
converter = DataRangeConverter(verbose=False)
test_values = [0, LIMITED_SOLID_COLOR_BLACK, SOLID_COLOR_MAX // 4, SOLID_COLOR_MAX // 2,
SOLID_COLOR_MAX * 3 // 4, LIMITED_SOLID_COLOR_WHITE, SOLID_COLOR_MAX]
2026-04-16 16:51:05 +08:00
print(" Full Range → Limited Range:")
for v in test_values:
limited = converter.convert_value(v)
diff = limited - v
print(f" {v:3d}{limited:3d} (差值: {diff:+3d})")
# 测试 2: RGB 转换
print("\n[测试 2] RGB 转换...")
test_rgb = [
(0, 0, 0),
(SOLID_COLOR_MAX // 2, SOLID_COLOR_MAX // 2, SOLID_COLOR_MAX // 2),
(SOLID_COLOR_MAX, SOLID_COLOR_MAX, SOLID_COLOR_MAX),
2026-04-16 16:51:05 +08:00
]
for r, g, b in test_rgb:
r_new, g_new, b_new = converter.convert_rgb(r, g, b)
print(f" RGB({r},{g},{b}) → RGB({r_new},{g_new},{b_new})")
# 测试 3: 完整转换流程
print("\n[测试 3] 完整转换流程...")
from app.ucd.solid_color_scale import byte_to_solid_color as _sc
2026-04-16 16:51:05 +08:00
pattern_params = [
[_sc(255)] * 3,
[_sc(230)] * 3,
[_sc(204)] * 3,
[_sc(128)] * 3,
[0, 0, 0],
2026-04-16 16:51:05 +08:00
]
converted = converter.convert(pattern_params, "Limited")
print("\n 对比:")
for i, (orig, conv) in enumerate(zip(pattern_params, converted)):
print(f" [{i+1}] {orig}{conv}")
# 测试 4: 便捷函数
print("\n[测试 4] 便捷函数...")
result = convert_pattern_params(
[[0, 0, 0], [SOLID_COLOR_MAX, SOLID_COLOR_MAX, SOLID_COLOR_MAX]], "Limited", verbose=False
2026-04-16 16:51:05 +08:00
)
print(f" 结果: {result}")
r, g, b = convert_single_rgb(SOLID_COLOR_MAX // 2, SOLID_COLOR_MAX // 2, SOLID_COLOR_MAX // 2, "Limited")
2026-04-16 16:51:05 +08:00
print(f" RGB(128,128,128) → RGB({r},{g},{b})")
# 测试 5: 获取信息
print("\n[测试 5] 转换器信息...")
info = converter.get_info()
for key, value in info.items():
print(f" {key}: {value}")
print("\n" + "=" * 80)
print("测试完成")
print("=" * 80)