修复1像素画笔绘制不连续问题并优化温度数据导出功能

This commit is contained in:
zqm
2025-11-12 09:01:32 +08:00
parent 5182f6c9bd
commit 958b2c974b
2 changed files with 136 additions and 22 deletions

View File

@@ -180,6 +180,18 @@
2. 移除所有已有的温差图例列表 2. 移除所有已有的温差图例列表
### btnLoadTempDiff加载温差图 ### btnLoadTempDiff加载温差图
### btnSaveTempDiff保存温差图 ### btnSaveTempDiff保存温差图
1. 弹出用户保存文件对话框,用户选择保存路径和文件名
2. 保存温差图例列表中的所有温差图例信息到csv文件
3. 每个温差图例信息占一行,格式为:
- 温度如20°C
- 颜色(如#FF0000表示红色
4. 保存温差图每个像素的温度值到csv文件
- 每个像素温度值占一行,格式为:
- X坐标如100
- Y坐标如300
- 温度值(°C)如25.5
#### 配置状态说明 #### 配置状态说明
1. 初始状态/就绪状态: 1. 初始状态/就绪状态:

View File

@@ -1909,7 +1909,11 @@ namespace JoyD.Windows.CS
adjustedBrushSize = Math.Min(adjustedBrushSize, 50); // 最大50像素 adjustedBrushSize = Math.Min(adjustedBrushSize, 50); // 最大50像素
} }
using (Pen pen = new Pen(selectedColor, adjustedBrushSize)) // 确保1像素画笔在任何缩放比例下都至少保持1像素宽
// 对于大于1像素的画笔继续使用缩放调整
int finalBrushSize = _currentBrushSize == 1 ? 1 : adjustedBrushSize;
using (Pen pen = new Pen(selectedColor, finalBrushSize))
{ {
pen.StartCap = LineCap.Round; pen.StartCap = LineCap.Round;
pen.EndCap = LineCap.Round; pen.EndCap = LineCap.Round;
@@ -1920,17 +1924,47 @@ namespace JoyD.Windows.CS
{ {
_lastDrawPoint = imagePoint; _lastDrawPoint = imagePoint;
// 绘制起始点的圆形 // 绘制起始点的圆形
int radius = adjustedBrushSize / 2; int radius = finalBrushSize / 2;
g.FillEllipse(new SolidBrush(selectedColor), g.FillEllipse(new SolidBrush(selectedColor),
imagePoint.X - radius, imagePoint.X - radius,
imagePoint.Y - radius, imagePoint.Y - radius,
adjustedBrushSize, finalBrushSize,
adjustedBrushSize); finalBrushSize);
} }
else else
{ {
// 绘制连线 // 计算两点之间的距离
int deltaX = Math.Abs(imagePoint.X - _lastDrawPoint.X);
int deltaY = Math.Abs(imagePoint.Y - _lastDrawPoint.Y);
int distance = (int)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
// 如果距离较大,添加中间点以确保线条连续
// 对于1像素画笔我们需要更密集的点来确保线条流畅
if (distance > finalBrushSize * 2 || (_currentBrushSize == 1 && distance > 2))
{
// 使用 Bresenham 算法的简化版本来绘制连续的线条
int steps = Math.Max(deltaX, deltaY);
float xIncrement = (float)(imagePoint.X - _lastDrawPoint.X) / steps;
float yIncrement = (float)(imagePoint.Y - _lastDrawPoint.Y) / steps;
Point currentPoint = _lastDrawPoint;
for (int i = 1; i <= steps; i++)
{
int nextX = (int)(_lastDrawPoint.X + xIncrement * i);
int nextY = (int)(_lastDrawPoint.Y + yIncrement * i);
Point nextPoint = new Point(nextX, nextY);
g.DrawLine(pen, currentPoint, nextPoint);
currentPoint = nextPoint;
}
}
else
{
// 距离较小时,直接绘制连线
g.DrawLine(pen, _lastDrawPoint, imagePoint); g.DrawLine(pen, _lastDrawPoint, imagePoint);
}
// 更新上一个点 // 更新上一个点
_lastDrawPoint = imagePoint; _lastDrawPoint = imagePoint;
} }
@@ -4112,6 +4146,30 @@ namespace JoyD.Windows.CS
Console.WriteLine("调整toolStrip尺寸失败: " + ex.Message); Console.WriteLine("调整toolStrip尺寸失败: " + ex.Message);
} }
} }
/// <summary>
/// 根据颜色查找对应的温度值
/// </summary>
/// <param name="color">要查找的颜色</param>
/// <returns>对应的温度值如果没有找到则返回null</returns>
private double? GetTemperatureByColor(Color color)
{
// 遍历温差图例数据,查找最接近的颜色
foreach (var item in tempDiffData)
{
Color legendColor = (Color)item["color"];
// 如果颜色完全匹配
if (legendColor.R == color.R && legendColor.G == color.G && legendColor.B == color.B)
{
string tempString = item["tempDiffValue"].ToString().Replace("°C", "").Trim();
return Convert.ToDouble(tempString);
}
}
// 如果没有找到完全匹配的颜色返回null
return null;
}
/// <summary> /// <summary>
/// 保存温差图例按钮点击事件处理程序 /// 保存温差图例按钮点击事件处理程序
/// </summary> /// </summary>
@@ -4151,24 +4209,68 @@ namespace JoyD.Windows.CS
writer.WriteLine("像素温度数据"); writer.WriteLine("像素温度数据");
writer.WriteLine("X坐标,Y坐标,温度值(°C)"); writer.WriteLine("X坐标,Y坐标,温度值(°C)");
// 保存温差图每个像素的温度值 // 从_tempDiffOverlayImage中获取真实温度数据
// 这里由于无法直接访问DeviceManager获取温度数据 if (_tempDiffOverlayImage != null && _tempDiffOverlayImage is Bitmap)
// 我们生成一些示例数据用于演示 {
// 在实际应用中应该通过Camera或DeviceManager获取真实的温度数据 Bitmap bitmap = (Bitmap)_tempDiffOverlayImage;
int width = 384; // 假设温度矩阵宽度
int height = 512; // 假设温度矩阵高度
// 生成示例温度数据(实际应用中应替换为真实数据) // 锁定位图以提高性能
Random random = new Random(); BitmapData bitmapData = bitmap.LockBits(
for (int y = 0; y < height; y += 10) // 为了减少文件大小每隔10个像素采样一次 new Rectangle(0, 0, bitmap.Width, bitmap.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format32bppArgb);
try
{ {
for (int x = 0; x < width; x += 10) int bytesPerPixel = 4; // 32bppArgb格式每像素4字节
int byteCount = bitmapData.Stride * bitmapData.Height;
byte[] pixels = new byte[byteCount];
// 将图像数据复制到数组
Marshal.Copy(bitmapData.Scan0, pixels, 0, byteCount);
// 遍历图像像素每隔10个像素采样一次以减少文件大小
for (int y = 0; y < bitmap.Height; y += 10)
{ {
double tempValue = 20.0 + random.NextDouble() * 30.0; // 生成20-50°C之间的随机温度 for (int x = 0; x < bitmap.Width; x += 10)
writer.WriteLine($"{x},{y},{tempValue:F1}"); {
// 计算当前像素在数组中的位置
int pixelIndex = y * bitmapData.Stride + x * bytesPerPixel;
// 获取像素颜色
byte b = pixels[pixelIndex];
byte g = pixels[pixelIndex + 1];
byte r = pixels[pixelIndex + 2];
byte a = pixels[pixelIndex + 3];
// 只处理非透明的像素
if (a > 0)
{
Color pixelColor = Color.FromArgb(a, r, g, b);
double? temperature = GetTemperatureByColor(pixelColor);
// 如果找到对应的温度值,则写入文件
if (temperature.HasValue)
{
writer.WriteLine($"{x},{y},{temperature.Value:F1}");
} }
} }
} }
}
}
finally
{
// 解锁位图
bitmap.UnlockBits(bitmapData);
}
}
else
{
// 如果没有温差图像数据,提示用户
writer.WriteLine("无温差图像数据");
MessageBox.Show("警告:未找到温差图像数据,仅保存了温差图例信息。", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
MessageBox.Show("温差图例和温度数据已成功保存到CSV文件", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information); MessageBox.Show("温差图例和温度数据已成功保存到CSV文件", "保存成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
} }