using System; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using EInk.Dtos; using EInk.Models; using Newtonsoft.Json; using SqlSugar; using SqlSugar.Extensions; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Rebar; namespace Eink.AOIDefectAnalysis { public partial class Form1 : Form { private List HeatPoints = new List(); Bitmap bMap; Bitmap bMap_New; ISqlSugarClient db; List Lot2DataList; private int Intense = 25; private int drift_x; private int drift_y; public Form1() { InitializeComponent(); Reset(); db = new SqlSugarClient(new ConnectionConfig() { DbType = DbType.PostgreSQL, ConnectionString = "Host=127.0.0.1;Port=5432;Database=Eink;Username=postgres;Password=eink;", IsAutoCloseConnection = true }); drift_x = panel1.Width / 2; drift_y = panel1.Height / 2; } private void generateBtn_Click(object sender, EventArgs e) { Reset(); for (int i = (int)startNUD.Value - 1; i < (int)startNUD.Value + (int)numNUD.Value - 1; i++) { Lot2Lot3Dto? lot2lot3 = JsonConvert.DeserializeObject(Lot2DataList[i].content); if (lot2lot3 != null && lot2lot3.result == "NG" && !generate_Picture(lot2lot3)) { dataGridView1.Rows.Add(new string[] { (i + 1).ToString(), lot2lot3.createTime, lot2lot3.slidesNumber, lot2lot3.result }); } } } private void clearBtn_Click(object sender, EventArgs e) { HeatPoints.Clear(); bMap = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(bMap)) { g.Clear(System.Drawing.Color.White); } bMap_New = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); UpdateView(); } private void UpdateView() { // 生成灰度热力图 bMap_New = CreateIntensityMask(bMap_New, HeatPoints); var bMap_byte_new = BitmapToByteArray(bMap_New); var bMap_byte = BitmapToByteArray(bMap); for (int i = 0; i < bMap_byte_new.Length; i++) { if (bMap_byte_new[i] != 255) { bMap_byte_new[i] = (byte)(255 - Intense); bMap_byte[i] = (byte)(bMap_byte[i] - Intense); } } label5.Text = ((255 - bMap_byte.Min()) / Intense).ToString(); bMap = ByteArrayToBitmap(bMap_byte, bMap.Width, bMap.Height); bMap_New = bMap; panel1.BackgroundImage = bMap_New; // 上色 bMap_New = Colorize(bMap_New, 255); panel2.BackgroundImage = bMap_New; } private Bitmap CreateIntensityMask(Bitmap bSurface, List aHeatPoints) { using (Graphics DrawSurface = Graphics.FromImage(bSurface)) { DrawSurface.Clear(System.Drawing.Color.White); foreach (HeatPoint DataPoint in aHeatPoints) { DrawHeatPoint(DrawSurface, DataPoint); // 绘制单色矩形 } } return bSurface; } private void DrawHeatPoint(Graphics Canvas, HeatPoint HeatPoint) { // 定义矩形区域 Rectangle rect = new Rectangle( HeatPoint.X - HeatPoint.Width / 2, HeatPoint.Y - HeatPoint.Height / 2, HeatPoint.Width, HeatPoint.Height ); // 创建图形路径 using (GraphicsPath path = new GraphicsPath()) { path.AddRectangle(rect); // 创建路径渐变笔刷 using (PathGradientBrush brush = new PathGradientBrush(path)) { var state = Canvas.Save(); // 设置中心颜色(保留原始透明度) System.Drawing.Color centerColor = System.Drawing.Color.FromArgb(HeatPoint.Intensity, System.Drawing.Color.Black); brush.CenterColor = centerColor; //设置边缘颜色为完全透明 System.Drawing.Color[] surroundColors = { System.Drawing.Color.Transparent }; brush.SurroundColors = surroundColors; //设置渐变焦点(控制渐变范围) brush.FocusScales = new PointF(0.6f, 1f); // 控制虚化范围 // 保存绘图状态 // 坐标变换 Canvas.TranslateTransform(HeatPoint.X, HeatPoint.Y); Canvas.RotateTransform(-HeatPoint.Rotation); Canvas.TranslateTransform(-HeatPoint.X, -HeatPoint.Y); // 填充路径 Canvas.FillPath(brush, path); // 恢复绘图状态 Canvas.Restore(state); } } } public static Bitmap Colorize(Bitmap Mask, byte Alpha) { Bitmap Output = new Bitmap(Mask.Width, Mask.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); Graphics Surface = Graphics.FromImage(Output); Surface.Clear(System.Drawing.Color.Transparent); // 构建一组颜色映射以将我们的灰度蒙版重新映射为全色 // 接受一个 alpha 字节来指定输出图像的透明度 ColorMap[] Colors = CreatePaletteIndex(Alpha); // 创建新的图像属性类来处理颜色重新映射 // 注入我们的颜色映射数组来指示图像属性类如何进行着色 ImageAttributes Remapper = new ImageAttributes(); Remapper.SetRemapTable(Colors); // 使用新的颜色映射方案将我们的蒙版绘制到我们的内存位图工作表面上 Surface.DrawImage(Mask, new System.Drawing.Rectangle(0, 0, Mask.Width, Mask.Height), 0, 0, Mask.Width, Mask.Height, GraphicsUnit.Pixel, Remapper); return Output; } private static ColorMap[] CreatePaletteIndex(byte Alpha) { ColorMap[] OutputMap = new ColorMap[256]; Assembly myAssembly = Assembly.GetExecutingAssembly(); Stream myStream = myAssembly.GetManifestResourceStream("Eink.AOIDefectAnalysis.Image.gradient-palette.jpg"); Bitmap Palette = new Bitmap(myStream); for (int X = 0; X <= 255; X++) { OutputMap[X] = new ColorMap(); OutputMap[X].OldColor = System.Drawing.Color.FromArgb(X, X, X); OutputMap[X].NewColor = System.Drawing.Color.FromArgb(Alpha, Palette.GetPixel(X, 0)); } return OutputMap; } private void Form1_Load(object sender, EventArgs e) { dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter; Lot2DataList = db.Queryable().Where(x => x.create_time >= DateTime.Parse($"2025-02-26 08:00:00")).ToList(); label2.Text = Lot2DataList.Count.ToString(); } public byte[] BitmapToByteArray(Bitmap bmp) { BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); // 计算Byte[]数组的大小 int bytesCount = bitmapData.Stride * bitmapData.Height; byte[] bmp_byte = new byte[bytesCount]; // 将像素数据复制到Byte[]数组 System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, bmp_byte, 0, bytesCount); // 释放资源 bmp.UnlockBits(bitmapData); return bmp_byte; } private Bitmap ByteArrayToBitmap(byte[] rgbaData, int width, int height) { var pixelFormat = PixelFormat.Format32bppArgb; Bitmap bitmap = new Bitmap(width, height, pixelFormat); BitmapData bitmapData = bitmap.LockBits( new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, pixelFormat); IntPtr intPtr = bitmapData.Scan0; System.Runtime.InteropServices.Marshal.Copy(rgbaData, 0, intPtr, rgbaData.Length); bitmap.UnlockBits(bitmapData); return bitmap; } private void dataGridView1_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) { HeatPoints.Clear(); bMap = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(bMap)) { g.Clear(System.Drawing.Color.White); } bMap_New = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); UpdateView(); var dataGridViewRow = dataGridView1.CurrentRow; int index = dataGridViewRow.Cells["Index"].Value.ObjToInt(); Lot2Lot3Dto? lot2lot3 = JsonConvert.DeserializeObject(Lot2DataList[index - 1].content); if (lot2lot3 != null && lot2lot3.result == "NG") { generate_Picture(lot2lot3); } } private bool generate_Picture(Lot2Lot3Dto lot2lot3) { bool skipflag = false; foreach (var itemCheckData in lot2lot3.itemCheckDatas) { if (skipflag || itemCheckData.details.Count >= 150) { skipflag = true; continue; } foreach (var detail in itemCheckData.details) { try { int iX = (int)(Convert.ToDouble(detail.x) * 3 / 2 + drift_x); int iY = (int)(Convert.ToDouble(detail.y) * 3 / 2 + drift_y); int Width = (int)(Convert.ToDouble(detail.width) * 3 / 2); int iWidth = Width <= 5 ? 5 : Width; int Height = (int)(Convert.ToDouble(detail.height) * 3 / 2); int iHeight = Height < 5 ? 5 : Height; byte iIntense = (byte)Intense; float iRotation = float.Parse(detail.rotation); HeatPoints.Add(new HeatPoint(iX, iY, iWidth, iHeight, iIntense, iRotation)); } catch (Exception) { continue; } } } if (!skipflag) { UpdateView(); HeatPoints.Clear(); } return skipflag; } private void Reset() { HeatPoints.Clear(); dataGridView1.Rows.Clear(); bMap = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); using (Graphics g = Graphics.FromImage(bMap)) { g.Clear(System.Drawing.Color.White); } bMap_New = new Bitmap((int)panel1.Width, (int)panel1.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb); } } }