quanzhou
2 天以前 86f899fa91e811415614dff1a699141144bfc802
src/Bro.M141.Process/M141Process_ImageCheck.cs
@@ -5,6 +5,7 @@
using Bro.DataBase.Model;
using Bro.M135.Common;
using Bro.M135.DBManager;
using Bro.UI.Model.Winform;
using HalconDotNet;
using Microsoft.VisualBasic;
using Newtonsoft.Json;
@@ -17,6 +18,7 @@
using System.Data;
using System.Data.SqlTypes;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.Net;
using System.Text;
using System.Text.Encodings.Web;
@@ -26,6 +28,7 @@
using static System.Net.Mime.MediaTypeNames;
using static System.Net.WebRequestMethods;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.Tab;
using File = System.IO.File;
namespace Bro.M141.Process
{
@@ -36,7 +39,7 @@
        ManualResetEvent set2 = new ManualResetEvent(false);
        public event Action<string> StartPrinter;
        [ProcessMethod("ImageCheck", "ImageCheckOperation", "通用图片检测操作", InvokeType.TestInvoke)]
        public ResponseMessage ImageCheckOperation(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
@@ -496,7 +499,6 @@
                Plc1.WriteSingleAddress(1526, mysqlhelper.GetS2Result(productList[0].SEQUENCE) ? 1 : 2, out _);
                LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{string.Join(",", productList.Select(u => u.PID))}检测反馈{mysqlhelper.GetS2Result(productList[0].SEQUENCE)}");
            }
            else
            {
@@ -701,11 +703,355 @@
                    imgSet.HImage?.Dispose();
                    imgSet.HImage = null;
                    Bitmap originImage = new Bitmap(imageFileNames[i]);
                    DetectResultSaveExcelAsync(detectResults, sn, originImage, DateTime.Now);
                }
            });
        }
        object _excelOpLock = new object();
        int _columnWidth = 0;
        int _columnWidth1 = 0;
        int _exportNum = 0;
        public async void DetectResultSaveExcelAsync(List<DetectResult> detectResults, string sn, Bitmap originImage, DateTime dt)
        {
            await Task.Run(() =>
            {
                if (detectResults.All(u => u.ResultState == EnumHelper.ResultState.OK))
                    return;
                try
                {
                    string excel_Path = Path.Combine(CSVHelper.BaseDirectory, $"{DateTime.Now.ToString("yyyyMMdd")}");
                    if (!Directory.Exists(excel_Path))//如果不存在就创建file文件夹
                    {
                        Directory.CreateDirectory(excel_Path);//创建该文件夹
                    }
                    excel_Path = Path.Combine(excel_Path, $"OfflineRecord_{DateTime.Now.ToString("yyyyMMdd")}.xlsx");
                    List<string> datas = new List<string>() { "检测时间", "SN", "缺陷名称", "位置", "缺陷面积", "实际面积", "缺陷截图1", "缺陷截图2" };
                    NPOI.SS.UserModel.IRow irow;
                    NPOI.SS.UserModel.ICell icell;
                    Interlocked.Increment(ref _exportNum);
                    lock (_excelOpLock)
                    {
                        if (!File.Exists(excel_Path))
                        {
                            XSSFWorkbook wb = new XSSFWorkbook();
                            ISheet sheet = wb.CreateSheet("DefectDetail");
                            irow = sheet.CreateRow(0);
                            for (int i = 0; i < datas.Count; i++)
                            {
                                icell = irow.CreateCell(i);
                                icell.SetCellValue(datas[i]);
                            }
                            FileStream fs = new FileStream(excel_Path, FileMode.OpenOrCreate, FileAccess.Write);
                            wb.Write(fs); fs.Close();
                            fs.Dispose();
                        }
                        using (FileStream newfs = new FileStream(excel_Path, FileMode.Open, FileAccess.ReadWrite))
                        {
                            //创建工作簿对象
                            XSSFWorkbook newwb = new XSSFWorkbook(newfs);
                            //根据工作表名获取工作簿对象,也可通过索引获取工作表wb.GetSheetAt(int index)
                            ISheet newsheet = newwb.GetSheet("DefectDetail");
                            int countrow = newsheet.LastRowNum + 1;
                            //ICellStyle hlink_style = newwb.CreateCellStyle();
                            //IFont hlink_font = newwb.CreateFont();
                            //hlink_font.Underline = FontUnderlineType.Single;
                            //hlink_font.Color = HSSFColor.Blue.Index;
                            //hlink_style.SetFont(hlink_font);
                            XSSFDrawing patriarchDefectImageFile = (XSSFDrawing)newsheet.CreateDrawingPatriarch();
                            var details = detectResults.SelectMany(u => u.NetResults).SelectMany(u => u.DetectDetails).Where(u => u.FinalResult != EnumHelper.ResultState.OK).ToList();
                            details.ForEach(d =>
                            {
                                //"检测时间", "SN", "缺陷名称", "位置", "缺陷面积", "实际面积", "缺陷截图1", "缺陷截图2"
                                List<string> data = new List<string>() { dt.ToString("HH:mm:ss.fff").ToString(), sn, d.ClassName, (d.Tag ?? "").ToString(), d.Area.ToString(), d.AreaInActual.ToString("f3") };
                                irow = newsheet.CreateRow(countrow);
                                for (int i = 0; i < datas.Count; i++)
                                {
                                    icell = irow.CreateCell(i);
                                    switch (i)
                                    {
                                        case 6:
                                            {
                                                byte[] bytesDefectImageFile = CaptureImage(originImage, (int)d.Rect.Width, (int)d.Rect.Height, (int)d.Rect.X, (int)d.Rect.Y, out int actWidth, out int actHeight);
                                                int pictureIdxDefectImageFile = newwb.AddPicture(bytesDefectImageFile, NPOI.SS.UserModel.PictureType.JPEG);
                                                // 插图片的位置  HSSFClientAnchor(dx1,dy1,dx2,dy2,col1,row1,col2,row2) 后面再作解释
                                                XSSFClientAnchor anchorDefectImageFile = new XSSFClientAnchor(1, 1, 1, 1, i, countrow, i + 1, countrow + 1);
                                                //把图片插到相应的位置
                                                XSSFPicture pictDefectImageFile = (XSSFPicture)patriarchDefectImageFile.CreatePicture(anchorDefectImageFile, pictureIdxDefectImageFile);
                                                ////int colWidth = actWidth * 32;
                                                ////if (colWidth > _columnWidth)
                                                ////{
                                                ////    _columnWidth = colWidth;
                                                ////    newsheet.SetColumnWidth(i, _columnWidth);
                                                ////}
                                                irow.Height = (short)(actHeight * 16);
                                                //pictDefectImageFile.Resize();
                                            }
                                            break;
                                        case 7:
                                            {
                                                byte[] bytesDefectImageFile = CaptureImage(originImage, (int)d.Rect.Width, (int)d.Rect.Height, (int)d.Rect.X, (int)d.Rect.Y, out int actWidth, out int actHeight, d);
                                                int pictureIdxDefectImageFile = newwb.AddPicture(bytesDefectImageFile, NPOI.SS.UserModel.PictureType.JPEG);
                                                XSSFClientAnchor anchorDefectImageFile = new XSSFClientAnchor(1, 1, 1, 1, i, countrow, i + 5, countrow + 1);
                                                //把图片插到相应的位置
                                                XSSFPicture pictDefectImageFile = (XSSFPicture)patriarchDefectImageFile.CreatePicture(anchorDefectImageFile, pictureIdxDefectImageFile);
                                                //int colWidth = actWidth * 32;
                                                //if (colWidth > _columnWidth1)
                                                //{
                                                //    _columnWidth1 = colWidth;
                                                //    newsheet.SetColumnWidth(i, _columnWidth1);
                                                //}
                                                //pictDefectImageFile.Resize();
                                            }
                                            break;
                                        default:
                                            string strvalue = data[i];
                                            icell.SetCellValue(strvalue);
                                            break;
                                    }
                                }
                                countrow++;
                            });
                            using (var temp = File.OpenWrite(excel_Path))
                            {
                                newwb.Write(temp);//向打开的这个xls文件中写入数据
                            }
                            newfs.Close();
                            newfs.Dispose();
                        }
                    }
                    Interlocked.Decrement(ref _exportNum);
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"{detectResults[0].PID}Excel输出完成,还有{_exportNum}条记录");
                }
                catch (Exception ex)
                {
                    LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"{detectResults[0].PID}缺陷插入Excel报错:{ex.Message.ToString()}");
                }
                finally
                {
                    originImage.Dispose();
                    originImage = null;
                }
            });
        }
        int _spaceRemain = 60;
        //public byte[] CaptureImage(Bitmap originImage, int width, int height, int spaceX, int spaceY, out int actWidth, out int actHeight, DefectDetail defect = null)
        //{
        //    spaceX -= _spaceRemain;
        //    spaceY -= _spaceRemain;
        //    width += _spaceRemain * 2;
        //    height += _spaceRemain * 2;
        //    if (spaceX < 0)
        //    {
        //        spaceX = 0;
        //    }
        //    if (spaceY < 0)
        //    {
        //        spaceY = 0;
        //    }
        //    if (spaceX + width > originImage.Width)
        //    {
        //        width = originImage.Width - spaceX;
        //    }
        //    if (spaceY + height > originImage.Height)
        //    {
        //        height = originImage.Height - spaceY;
        //    }
        //    actHeight = height;
        //    actWidth = width;
        //    Bitmap imageBack = originImage;
        //    if (defect != null)
        //    {
        //        PolygonResultDisplay display = new PolygonResultDisplay(defect, defect.ClassName, Color.Red, false, (int)(width * GlobalVar.WIDTH_RATIO));
        //        imageBack = new Bitmap(originImage.Width, originImage.Height, PixelFormat.Format24bppRgb);
        //        using (Graphics g = Graphics.FromImage(imageBack))
        //        {
        //            g.DrawImage(originImage, 0, 0);
        //            display.Draw(g);
        //        }
        //    }
        //    //创建新图位图
        //    Bitmap bitmap = new Bitmap(width, height, imageBack.PixelFormat);
        //    //创建作图区域
        //    using (Graphics graphic = Graphics.FromImage(bitmap))
        //    {
        //        //截取原图相应区域写入作图区
        //        graphic.DrawImage(imageBack, 0, 0, new Rectangle(spaceX, spaceY, width, height), GraphicsUnit.Pixel);
        //    }
        //    byte[] bt = null;
        //    using (MemoryStream mostream = new MemoryStream())
        //    {
        //        bitmap.Save(mostream, System.Drawing.Imaging.ImageFormat.Bmp);//将图像以指定的格式存入缓存内存流
        //        bt = new byte[mostream.Length];
        //        mostream.Position = 0;//设置留的初始位置
        //        mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
        //    }
        //    bitmap.Dispose();
        //    return bt;
        //}
        public byte[] CaptureImage(Bitmap originImage, int width, int height, int spaceX, int spaceY,
    out int actWidth, out int actHeight, DefectDetail defect = null)
        {
            spaceX -= _spaceRemain;
            spaceY -= _spaceRemain;
            width += _spaceRemain * 2;
            height += _spaceRemain * 2;
            if (spaceX < 0)
            {
                spaceX = 0;
            }
            if (spaceY < 0)
            {
                spaceY = 0;
            }
            if (spaceX + width > originImage.Width)
            {
                width = originImage.Width - spaceX;
            }
            if (spaceY + height > originImage.Height)
            {
                height = originImage.Height - spaceY;
            }
            actHeight = height;
            actWidth = width;
            Bitmap imageBack = originImage;
            bool needDisposeImageBack = false; // 新增:标记是否需要释放imageBack
            if (defect != null)
            {
                PolygonResultDisplay display = new PolygonResultDisplay(defect, defect.ClassName, Color.Red, false, (int)(width * GlobalVar.WIDTH_RATIO));
                // 修改点1:确保创建的Bitmap支持Graphics
                // 使用Format24bppRgb或Format32bppArgb
                imageBack = new Bitmap(originImage.Width, originImage.Height, PixelFormat.Format24bppRgb);
                needDisposeImageBack = true; // 标记为需要释放
                // 修改点2:检查原始图像格式,如果是索引格式需要特殊处理
                if (IsIndexedPixelFormat(originImage.PixelFormat))
                {
                    // 创建支持Graphics的格式
                    using (Bitmap tempImage = new Bitmap(originImage.Width, originImage.Height, PixelFormat.Format24bppRgb))
                    using (Graphics tempG = Graphics.FromImage(tempImage))
                    {
                        tempG.DrawImage(originImage, 0, 0);
                        using (Graphics g = Graphics.FromImage(imageBack))
                        {
                            g.DrawImage(tempImage, 0, 0);
                            display.Draw(g);
                        }
                    }
                }
                else
                {
                    // 原始代码逻辑
                    using (Graphics g = Graphics.FromImage(imageBack))
                    {
                        g.DrawImage(originImage, 0, 0);
                        display.Draw(g);
                    }
                }
            }
            else if (IsIndexedPixelFormat(originImage.PixelFormat))
            {
                // 修改点3:即使没有defect,如果是索引格式也需要转换
                imageBack = new Bitmap(originImage.Width, originImage.Height, PixelFormat.Format24bppRgb);
                needDisposeImageBack = true;
                using (Graphics g = Graphics.FromImage(imageBack))
                {
                    g.DrawImage(originImage, 0, 0);
                }
            }
            // 修改点4:确保bitmap的像素格式支持Graphics
            PixelFormat bitmapFormat = imageBack.PixelFormat;
            if (IsIndexedPixelFormat(bitmapFormat))
            {
                // 如果imageBack仍然是索引格式(理论上不应该),转换为支持格式
                bitmapFormat = PixelFormat.Format24bppRgb;
            }
            //创建新图位图
            Bitmap bitmap = new Bitmap(width, height, bitmapFormat);
            //创建作图区域
            using (Graphics graphic = Graphics.FromImage(bitmap))
            {
                //截取原图相应区域写入作图区
                graphic.DrawImage(imageBack, 0, 0, new Rectangle(spaceX, spaceY, width, height), GraphicsUnit.Pixel);
            }
            byte[] bt = null;
            using (MemoryStream mostream = new MemoryStream())
            {
                bitmap.Save(mostream, System.Drawing.Imaging.ImageFormat.Bmp);//将图像以指定的格式存入缓存内存流
                bt = new byte[mostream.Length];
                mostream.Position = 0;//设置留的初始位置
                mostream.Read(bt, 0, Convert.ToInt32(bt.Length));
            }
            bitmap.Dispose();
            // 修改点5:释放临时创建的imageBack
            if (needDisposeImageBack && imageBack != originImage)
            {
                imageBack.Dispose();
            }
            return bt;
        }
        // 新增辅助方法:检查是否为索引像素格式
        private bool IsIndexedPixelFormat(PixelFormat format)
        {
            return format == PixelFormat.Format1bppIndexed ||
                   format == PixelFormat.Format4bppIndexed ||
                   format == PixelFormat.Format8bppIndexed ||
                   format == PixelFormat.Indexed;
        }
        [ProcessMethod("printer", "printer", "打印机打印", InvokeType.TestInvoke)]
        public ResponseMessage Printer(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice)
@@ -713,8 +1059,13 @@
            ResponseMessage msg = new ResponseMessage();
            Plc2 = invokeDevice as PLCBase;
            string message = "";
            StartPrinter.Invoke(message);
            //string message = "nothing";
            if (M141Config.MES_codes.Count >= 1)
            {
                string message = M141Config.MES_codes[0].Printers_code;
                StartPrint(message, "Honeywell PX240S(300 dpi)1");
                M141Config.MES_codes.RemoveAt(0);
            }
            return msg;
        }
@@ -988,5 +1339,14 @@
            public object data { get; set; }
        }
    }
}