diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs b/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs index 53061e7..8fd26b5 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/TemperatureData.cs @@ -80,7 +80,7 @@ namespace JoyD.Windows.CS.Toprie } /// - /// 解析原始温度数据 + /// 解析原始温度数据,支持根据数据长度自适应宽高 /// /// 原始温度数据 /// 温度补偿值 @@ -104,39 +104,62 @@ namespace JoyD.Windows.CS.Toprie throw new ArgumentException("温度数据头部信息无效"); } + // 从头部解析温度数据长度 + int payloadLength = GetPayloadLengthFromHeader(rawData); + int actualDataLength = rawData.Length - 24; // 实际温度数据长度(总长度减去头部长度) + + // 验证数据长度一致性 + if (payloadLength > 0 && payloadLength != actualDataLength) + { + System.Diagnostics.Debug.WriteLine($"警告: 头部指定的数据长度({payloadLength})与实际数据长度({actualDataLength})不匹配"); + // 但我们仍然使用实际数据长度继续处理 + } + + // 根据数据长度自适应确定宽高 + int pixelCount = actualDataLength / 2; // 每个像素点2字节 + int[] widthHeight = GetWidthHeightByPixelCount(pixelCount); + int adaptiveWidth = widthHeight[0]; + int adaptiveHeight = widthHeight[1]; + + // 输出自适应宽高信息 + System.Diagnostics.Debug.WriteLine($"根据数据长度自适应宽高: {adaptiveWidth}x{adaptiveHeight} (像素数: {pixelCount})"); + + // 如果自适应宽高与传入的宽高不同,更新宽高并重新初始化矩阵 + bool isAdaptiveResolution = false; + if (adaptiveWidth != Width || adaptiveHeight != Height) + { + isAdaptiveResolution = true; + Width = adaptiveWidth; + Height = adaptiveHeight; + TemperatureMatrix = new float[Height, Width]; + System.Diagnostics.Debug.WriteLine($"注意: 使用自适应宽高替换了原始宽高设置"); + } + // 跳过24字节的头部信息 int dataIndex = 24; - // 确保跳过头部后仍有足够的数据用于解析 - int requiredDataLength = Width * Height * 2; // 每个温度点2字节 - if (rawData.Length - dataIndex < requiredDataLength) - { - System.Diagnostics.Debug.WriteLine($"警告: 数据长度不足,需要{requiredDataLength}字节温度数据,但实际只有{rawData.Length - dataIndex}字节"); - throw new ArgumentException("原始数据长度不足以包含完整的温度数据"); - } + // 计算最大可处理的像素数 + int maxPixels = Math.Min(pixelCount, Width * Height); // 遍历所有像素点,按顺序处理温度数据 - for (int row = 0; row < Height; row++) + for (int row = 0; row < Height && dataIndex + 1 < rawData.Length; row++) { - for (int col = 0; col < Width; col++) + for (int col = 0; col < Width && dataIndex + 1 < rawData.Length; col++) { - if (dataIndex + 1 < rawData.Length) - { - // 按照SDK实际实现计算温度值:摄氏温度=(L + H*256 - 2730)/10 - // 注意:SDK实现是低字节在前,高字节在后,且包含2730的开尔文到摄氏度转换 - int lowByte = rawData[dataIndex]; - int highByte = rawData[dataIndex + 1]; - float rawTemperature = (lowByte + highByte * 256 - 2730) / 10.0f; - float compensatedTemperature = rawTemperature + compensationValue; - - // 原始温度存入TemperatureMatrix(未温补) - TemperatureMatrix[row, col] = rawTemperature; - - // 温补后的温度存入RealTemperatureMatrix(映射到512×384矩阵) - MapToRealTemperatureMatrix(row, col, compensatedTemperature); - - dataIndex += 2; - } + // 按照SDK实际实现计算温度值:摄氏温度=(L + H*256 - 2730)/10 + // 注意:SDK实现是低字节在前,高字节在后,且包含2730的开尔文到摄氏度转换 + int lowByte = rawData[dataIndex]; + int highByte = rawData[dataIndex + 1]; + float rawTemperature = (lowByte + highByte * 256 - 2730) / 10.0f; + float compensatedTemperature = rawTemperature + compensationValue; + + // 原始温度存入TemperatureMatrix(未温补) + TemperatureMatrix[row, col] = rawTemperature; + + // 温补后的温度存入RealTemperatureMatrix(映射到512×384矩阵) + MapToRealTemperatureMatrix(row, col, compensatedTemperature); + + dataIndex += 2; } } } @@ -326,30 +349,81 @@ namespace JoyD.Windows.CS.Toprie /// 如果头部信息有效返回true,否则返回false private bool ValidateHeader(byte[] rawData) { - // 根据SDK文档,头部信息的前几个字节通常包含标识字符或特定模式 - // 这里实现基本验证,可以根据SDK文档的具体规范进行扩展 + // 根据SDK文档,头部信息的前几个字节包含标识字符和数据长度 // 检查原始数据不为空且长度足够 if (rawData == null || rawData.Length < 24) return false; - // 示例验证逻辑:可以根据实际SDK文档中的头部格式规范进行调整 - // 1. 检查数据长度是否合理(至少包含头部+最小温度数据) + // 1. 验证头部标识字符是否为"+TEMP" + string headerMark = Encoding.ASCII.GetString(rawData, 0, 5).TrimEnd('\0'); + if (headerMark != "+TEMP") + { + System.Diagnostics.Debug.WriteLine($"警告: 头部标识不匹配,期望'+TEMP',实际为'{headerMark}'"); + return false; + } + + // 2. 检查数据长度是否合理(至少包含头部+最小温度数据) if (rawData.Length < 24 + 2) // 24字节头部 + 至少1个温度点(2字节) return false; - // 2. 如果SDK文档中定义了特定的头部标识,可以在这里验证 - // 例如:检查前4个字节是否为特定的魔术数字 - // uint magicNumber = BitConverter.ToUInt32(rawData, 0); - // if (magicNumber != 0x12345678) // 假设的魔术数字 - // return false; - - // 3. 可以验证头部中的某些字段是否在合理范围内 - // 例如:宽度、高度等信息 - - // 目前实现的是基本验证,根据实际SDK规范可以扩展更详细的验证逻辑 return true; } + + /// + /// 从头部解析温度数据长度 + /// + /// 包含头部信息的原始数据 + /// 温度数据长度(字节数) + private int GetPayloadLengthFromHeader(byte[] rawData) + { + // 根据SDK文档,payload_length在头部的第5-8字节 + // 注意:SDK文档指出采用低字节在前的存储方式 + if (rawData.Length >= 9) + { + return BitConverter.ToInt32(rawData, 5); + } + return 0; + } + + /// + /// 根据像素数量和已知分辨率比例推算宽高 + /// + /// 像素总数 + /// 宽高数组,格式为[宽度, 高度] + private int[] GetWidthHeightByPixelCount(int pixelCount) + { + // 已知设备支持的分辨率比例为4:3 + // 检查是否为标准分辨率: + // 240×180 = 43200像素 + // 384×288 = 110592像素 + + // 标准分辨率映射 + var standardResolutions = new Dictionary { + { 43200, new int[] { 240, 180 } }, + { 110592, new int[] { 384, 288 } } + }; + + // 如果匹配标准分辨率,安全地返回对应值 + int[] resolution; + if (standardResolutions.TryGetValue(pixelCount, out resolution)) + { + return resolution; + } + + // 否则尝试根据像素数推算最接近4:3比例的宽高 + float ratio = 4.0f / 3.0f; + int width = (int)Math.Sqrt(pixelCount * ratio); + int height = (int)(width / ratio); + + // 确保宽高相乘尽可能接近像素数 + while (width * height < pixelCount && width * (height + 1) <= pixelCount) + { + height++; + } + + return new int[] { width, height }; + } } ///