From 958b2c974b4267f38c5cbd022d261e59d96fbd9c Mon Sep 17 00:00:00 2001 From: zqm Date: Wed, 12 Nov 2025 09:01:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D1=E5=83=8F=E7=B4=A0=E7=94=BB?= =?UTF-8?q?=E7=AC=94=E7=BB=98=E5=88=B6=E4=B8=8D=E8=BF=9E=E7=BB=AD=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B8=A9=E5=BA=A6=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CS/Framework4.0/Toprie/Toprie/README.md | 12 ++ .../CS/Framework4.0/Toprie/Toprie/Setting.cs | 146 +++++++++++++++--- 2 files changed, 136 insertions(+), 22 deletions(-) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/README.md b/Windows/CS/Framework4.0/Toprie/Toprie/README.md index 7c609ce..68e766a 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/README.md +++ b/Windows/CS/Framework4.0/Toprie/Toprie/README.md @@ -180,6 +180,18 @@ 2. 移除所有已有的温差图例列表 ### btnLoadTempDiff(加载温差图) ### btnSaveTempDiff(保存温差图) +1. 弹出用户保存文件对话框,用户选择保存路径和文件名 +2. 保存温差图例列表中的所有温差图例信息到csv文件 +3. 每个温差图例信息占一行,格式为: + - 温度(如20°C) + - 颜色(如#FF0000表示红色) +4. 保存温差图每个像素的温度值到csv文件 + - 每个像素温度值占一行,格式为: + - X坐标(如100) + - Y坐标(如300) + - 温度值(°C)(如25.5) + + #### 配置状态说明 1. 初始状态/就绪状态: diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs index 6286bc7..0e093de 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs @@ -1909,28 +1909,62 @@ namespace JoyD.Windows.CS 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.EndCap = LineCap.Round; pen.LineJoin = LineJoin.Round; // 如果是首次绘制或上一个点无效,记录当前点作为起点 if (_lastDrawPoint == Point.Empty) - { + { _lastDrawPoint = imagePoint; // 绘制起始点的圆形 - int radius = adjustedBrushSize / 2; + int radius = finalBrushSize / 2; g.FillEllipse(new SolidBrush(selectedColor), imagePoint.X - radius, imagePoint.Y - radius, - adjustedBrushSize, - adjustedBrushSize); + finalBrushSize, + finalBrushSize); } else - { - // 绘制连线 - g.DrawLine(pen, _lastDrawPoint, imagePoint); + { + // 计算两点之间的距离 + 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); + } + // 更新上一个点 _lastDrawPoint = imagePoint; } @@ -4112,6 +4146,30 @@ namespace JoyD.Windows.CS Console.WriteLine("调整toolStrip尺寸失败: " + ex.Message); } } + /// + /// 根据颜色查找对应的温度值 + /// + /// 要查找的颜色 + /// 对应的温度值,如果没有找到则返回null + 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; + } + /// /// 保存温差图例按钮点击事件处理程序 /// @@ -4151,22 +4209,66 @@ namespace JoyD.Windows.CS writer.WriteLine("像素温度数据"); writer.WriteLine("X坐标,Y坐标,温度值(°C)"); - // 保存温差图每个像素的温度值 - // 这里由于无法直接访问DeviceManager获取温度数据 - // 我们生成一些示例数据用于演示 - // 在实际应用中,应该通过Camera或DeviceManager获取真实的温度数据 - int width = 384; // 假设温度矩阵宽度 - int height = 512; // 假设温度矩阵高度 - - // 生成示例温度数据(实际应用中应替换为真实数据) - Random random = new Random(); - for (int y = 0; y < height; y += 10) // 为了减少文件大小,每隔10个像素采样一次 + // 从_tempDiffOverlayImage中获取真实温度数据 + if (_tempDiffOverlayImage != null && _tempDiffOverlayImage is Bitmap) { - for (int x = 0; x < width; x += 10) + Bitmap bitmap = (Bitmap)_tempDiffOverlayImage; + + // 锁定位图以提高性能 + BitmapData bitmapData = bitmap.LockBits( + new Rectangle(0, 0, bitmap.Width, bitmap.Height), + ImageLockMode.ReadOnly, + PixelFormat.Format32bppArgb); + + try { - double tempValue = 20.0 + random.NextDouble() * 30.0; // 生成20-50°C之间的随机温度 - writer.WriteLine($"{x},{y},{tempValue:F1}"); + 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) + { + for (int x = 0; x < bitmap.Width; x += 10) + { + // 计算当前像素在数组中的位置 + 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); } }