# -*- 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)