Files
pqAutomationApp/app/data_range_converter.py
2026-04-21 15:31:48 +08:00

289 lines
7.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: UTF-8 -*-
"""
数据范围转换器
将 Full Range (0-255) 转换为 Limited Range (16-235)
使用方法:
from app.data_range_converter import DataRangeConverter
converter = DataRangeConverter()
converted_params = converter.convert(pattern_params, "Limited")
"""
class DataRangeConverter:
"""数据范围转换器"""
def __init__(self, verbose=True):
"""
初始化转换器
Args:
verbose: 是否打印详细日志
"""
self.verbose = verbose
def convert_value(self, value):
"""
将单个 Full Range 值转换为 Limited Range
转换公式:
limited = 16 + (value / 255) × (235 - 16)
Args:
value: Full Range 值 (0-255)
Returns:
int: Limited Range 值 (16-235)
"""
# 边界值直接映射
if value == 0:
return 16
elif value == 255:
return 235
else:
# 线性映射
limited = 16 + round((value / 255.0) * (235 - 16))
# 限制范围
return max(16, min(235, limited))
def convert_rgb(self, r, g, b):
"""
转换单个 RGB 值
Args:
r, g, b: Full Range RGB 值 (0-255)
Returns:
tuple: Limited Range RGB 值 (16-235)
"""
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("使用 Full Range (0-255),无需转换")
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 (16-235)")
print(" 转换公式: 16 + (value / 255) × (235 - 16)")
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
# 第一个和最后一个
if index == 0:
should_print = True
label = "黑色"
elif index == len([]) - 1: # 需要在外部判断
should_print = True
label = "白色"
# 关键 RGB 值
elif (
r_orig in [0, 128, 255]
or g_orig in [0, 128, 255]
or b_orig in [0, 128, 255]
):
should_print = True
if r_orig == 128:
label = "50%"
else:
label = ""
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):
"""打印转换尾部信息"""
print(f"转换完成,共 {total_count} 个图案")
print("=" * 80)
def get_info(self):
"""获取转换器信息"""
return {
"name": "Data Range Converter",
"version": "1.0.0",
"full_range": "0-255",
"limited_range": "16-235",
"formula": "16 + (value / 255) × 219",
}
# ========== 便捷函数 ==========
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: 转换后的图案参数列表
示例:
>>> from app.data_range_converter import convert_pattern_params
>>> params = [[0,0,0], [255,255,255]]
>>> converted = convert_pattern_params(params, "Limited")
[[16,16,16], [235,235,235]]
"""
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 值 (0-255)
data_range: "Full""Limited"
Returns:
tuple: 转换后的 RGB 值
示例:
>>> from app.data_range_converter import convert_single_rgb
>>> 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, 16, 64, 128, 192, 235, 255]
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),
(128, 128, 128),
(255, 255, 255),
]
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] 完整转换流程...")
pattern_params = [
[255, 255, 255], # 100% 白
[230, 230, 230], # 90%
[204, 204, 204], # 80%
[128, 128, 128], # 50%
[0, 0, 0], # 0% 黑
]
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], [255, 255, 255]], "Limited", verbose=False
)
print(f" 结果: {result}")
r, g, b = convert_single_rgb(128, 128, 128, "Limited")
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)