修复GetWidthHeightByPixelCount方法中可能引发的KeyNotFoundException异常

This commit is contained in:
zqm
2025-10-31 11:38:52 +08:00
parent de511c8f2f
commit 22969da252

View File

@@ -80,7 +80,7 @@ namespace JoyD.Windows.CS.Toprie
}
/// <summary>
/// 解析原始温度数据
/// 解析原始温度数据,支持根据数据长度自适应宽高
/// </summary>
/// <param name="rawData">原始温度数据</param>
/// <param name="compensationValue">温度补偿值</param>
@@ -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
/// <returns>如果头部信息有效返回true否则返回false</returns>
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;
}
/// <summary>
/// 从头部解析温度数据长度
/// </summary>
/// <param name="rawData">包含头部信息的原始数据</param>
/// <returns>温度数据长度(字节数)</returns>
private int GetPayloadLengthFromHeader(byte[] rawData)
{
// 根据SDK文档payload_length在头部的第5-8字节
// 注意SDK文档指出采用低字节在前的存储方式
if (rawData.Length >= 9)
{
return BitConverter.ToInt32(rawData, 5);
}
return 0;
}
/// <summary>
/// 根据像素数量和已知分辨率比例推算宽高
/// </summary>
/// <param name="pixelCount">像素总数</param>
/// <returns>宽高数组,格式为[宽度, 高度]</returns>
private int[] GetWidthHeightByPixelCount(int pixelCount)
{
// 已知设备支持的分辨率比例为4:3
// 检查是否为标准分辨率:
// 240×180 = 43200像素
// 384×288 = 110592像素
// 标准分辨率映射
var standardResolutions = new Dictionary<int, int[]> {
{ 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 };
}
}
/// <summary>