| | |
| | | using Bro.Common.Helper; |
| | | using Bro.Common.Interface; |
| | | using Bro.Common.Model; |
| | | 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; |
| | | using Newtonsoft.Json.Linq; |
| | | using NPOI.SS.Formula.Functions; |
| | | using NPOI.SS.UserModel; |
| | | using NPOI.Util; |
| | | using NPOI.XSSF.UserModel; |
| | |
| | | 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; |
| | |
| | | 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 |
| | | { |
| | |
| | | ManualResetEvent set2 = new ManualResetEvent(false); |
| | | |
| | | |
| | | public event Action<string> StartPrinter; |
| | | |
| | | |
| | | [ProcessMethod("ImageCheck", "ImageCheckOperation", "通用图片检测操作", InvokeType.TestInvoke)] |
| | | public ResponseMessage ImageCheckOperation(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice) |
| | |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | |
| | |
| | | public ResponseMessage ProductDataUpload(IOperationConfig config, IDevice invokeDevice, IDevice sourceDevice) |
| | | { |
| | | ResponseMessage msg = new ResponseMessage(); |
| | | string inputSequence = Plc1.Read(1536, 1, out _)[0].ToString(); |
| | | int numplca = Plc1.Read(1536, 1, out _)[0]; |
| | | string inputSequence = numplca.ToString(); |
| | | |
| | | var productList = new List<int>() { 1 }.Select(u => |
| | | { |
| | |
| | | return FindProductBySequence(sequence, true); |
| | | }).ToList(); |
| | | |
| | | if (PlcNumForAll == -1) |
| | | { |
| | | PlcNumForAll = numplca; |
| | | } |
| | | |
| | | int waitInterval = 300; |
| | | int repeatTime = M141Config.DetectTimeout / waitInterval; |
| | |
| | | } while (true); |
| | | |
| | | |
| | | var Defaultclass = M141Config.DefectClassCollection.FirstOrDefault(u => u.IsDefault); |
| | | productList.ForEach(p => |
| | | { |
| | | if (Defaultclass == null) |
| | | { |
| | | if (string.IsNullOrEmpty(p.Result)) |
| | | { |
| | | p.Result = "NG"; |
| | | } |
| | | } |
| | | else |
| | | { |
| | | if (string.IsNullOrEmpty(p.Result)) |
| | | { |
| | | p.Result = Defaultclass.ClassName; |
| | | } |
| | | } |
| | | var Defaultclass = M141Config.DefectClassCollection.FirstOrDefault(u => u.ClassName == productList[0].Result); |
| | | |
| | | Plc1.WriteSingleAddress(1526, p.Result.ToUpper().Contains("NG") ? 2 : 1, out _); |
| | | }); |
| | | if (M141Config.StationCode == "S4" && productList[0].Result == "OK") |
| | | { |
| | | ////mysqlhelper.GetS2Result(productList[0].SEQUENCE); |
| | | 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 |
| | | { |
| | | Plc1.WriteSingleAddress(1526, Defaultclass?.ClassValue ?? 2, out _); |
| | | } |
| | | |
| | | Plc1.WriteSingleAddress(1516, 1, out _); |
| | | |
| | | //if (M141Config.ISupMES && (M141Config.MESchannel == -1 || M141Config.MESchannel == 1)) |
| | | //{ |
| | | // if (M141Config.numpro >= 50) |
| | | // { |
| | | // M141Config.numpro = 0; |
| | | // } |
| | | |
| | | // if (productList[0].Result == "OK") |
| | | // { |
| | | // M141Config.numpro++; |
| | | // } |
| | | |
| | | // //mqtt.demes(productList[0], M141Config.zwoid); |
| | | // string Msgreceice = Task.Run(() => mqtt.MESForProduceAsync(productList[0], M141Config.zwoid, M141Config.numpro)).Result; |
| | | // if (Msgreceice == null) |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{productList[0].PID}数据上传MES异常 返回数据为null"); |
| | | // } |
| | | // else |
| | | // { |
| | | // try |
| | | // { |
| | | // var obj = JsonConvert.DeserializeObject<AutoLineMacBarcodeQueueBak>(Msgreceice); |
| | | |
| | | // if (obj.zstatus == "200") |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"产品{productList[0].PID}数据上传MES成功 {Msgreceice}"); |
| | | // } |
| | | // else |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{productList[0].PID}数据上传MES失败 {Msgreceice}"); |
| | | // } |
| | | // } |
| | | // catch |
| | | // { |
| | | // LogAsync(DateTime.Now, EnumHelper.LogLevel.Exception, $"产品{productList[0].PID}数据上传MES异常 {Msgreceice}"); |
| | | // } |
| | | // } |
| | | |
| | | |
| | | |
| | | // lock (plcnumlock) |
| | | // { |
| | | // int differ = numplca - PlcNumForAll; |
| | | // if (differ > 1) |
| | | // { |
| | | // for (int i = PlcNumForAll + 1; i < numplca; i++) |
| | | // { |
| | | // try |
| | | // { |
| | | // var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | // ProductModel newp = new ProductModel(); |
| | | // newp.SEQUENCE = plist[0].SEQUENCE; |
| | | // newp.PID = plist[0].PID; |
| | | // newp.BasketCode = plist[0].BasketCode; |
| | | // newp.Result = "NG"; |
| | | // newp.SN = plist[0].SN; |
| | | // var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.zwoid, M141Config.numpro)).Result; |
| | | |
| | | // } |
| | | // catch |
| | | // { |
| | | |
| | | // } |
| | | // } |
| | | // } |
| | | // else if (differ != -29998) |
| | | // { |
| | | // for (int i = PlcNumForAll + 1; i <= 29999; i++) |
| | | // { |
| | | // try |
| | | // { |
| | | // var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | // ProductModel newp = new ProductModel(); |
| | | // newp.SEQUENCE = plist[0].SEQUENCE; |
| | | // newp.PID = plist[0].PID; |
| | | // newp.BasketCode = plist[0].BasketCode; |
| | | // newp.Result = "NG"; |
| | | // newp.SN = plist[0].SN; |
| | | // var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.zwoid, M141Config.numpro)).Result; |
| | | |
| | | // } |
| | | // catch |
| | | // { |
| | | |
| | | // } |
| | | // } |
| | | |
| | | |
| | | |
| | | // for (int i = 1; i < numplca; i++) |
| | | // { |
| | | // try |
| | | // { |
| | | // var plist = mysqlhelper.GetProductList(i + "_1"); |
| | | // ProductModel newp = new ProductModel(); |
| | | // newp.SEQUENCE = plist[0].SEQUENCE; |
| | | // newp.PID = plist[0].PID; |
| | | // newp.BasketCode = plist[0].BasketCode; |
| | | // newp.Result = "NG"; |
| | | // newp.SN = plist[0].SN; |
| | | // var tems = Task.Run(() => mqtt.MESForProduceAsync(newp, M141Config.zwoid, M141Config.numpro)).Result; |
| | | |
| | | // } |
| | | // catch |
| | | // { |
| | | |
| | | // } |
| | | // } |
| | | |
| | | |
| | | // } |
| | | // PlcNumForAll = numplca; |
| | | // } |
| | | |
| | | //} |
| | | |
| | | return msg; |
| | | } |
| | | |
| | | object plcnumlock = new object(); |
| | | int PlcNumForAll = -1; |
| | | |
| | | private bool _isDemoStarted = false; |
| | | [ProcessMethod("OfflineDemo", "OfflineDemo", "离线测试", InvokeType.CalibInvoke)] |
| | |
| | | else |
| | | { |
| | | _isDemoStarted = true; |
| | | OfflineDemoAsync(opConfig.ImageFolder); |
| | | OfflineDemoAsync(opConfig.ImageFolder, opConfig.IsOK, opConfig.SaveImageTime); |
| | | } |
| | | } |
| | | |
| | | return new ResponseMessage(); |
| | | } |
| | | |
| | | private async void OfflineDemoAsync(string imageFolder) |
| | | private async void OfflineDemoAsync(string imageFolder, bool isok, int saveimagetime) |
| | | { |
| | | await Task.Run(() => |
| | | { |
| | |
| | | { |
| | | return; |
| | | } |
| | | |
| | | var imageFile = Path.GetFileNameWithoutExtension(imageFileNames[i]); |
| | | if (imageFile.EndsWith("Fit")) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | var nameDatas = imageFile.Split(new char[] { '_'}, StringSplitOptions.RemoveEmptyEntries).ToList(); |
| | | if (imageFile.EndsWith("OK") & isok == false) |
| | | { |
| | | continue; |
| | | } |
| | | if (imageFile.EndsWith("NG") & isok == true) |
| | | { |
| | | continue; |
| | | } |
| | | var nameDatas = imageFile.Split(new char[] { '_' }, StringSplitOptions.RemoveEmptyEntries).ToList(); |
| | | if (nameDatas.Count != 5) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Error, $"文件{imageFile}命名不符合规范,不执行离线测试"); |
| | | continue; |
| | | } |
| | | |
| | | var sn = nameDatas[0]; |
| | | var imageSeq = nameDatas[1]; |
| | | |
| | | var sn = nameDatas[0] + "_1"; |
| | | var imageSeq = nameDatas[2][^1].ToString(); |
| | | var measureBind = M141Config.MeasureBindCollection.FirstOrDefault(u => u.ImageSaveSeq == imageSeq); |
| | | |
| | | if (measureBind == null || !measureBind.IsFixed) |
| | | { |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Assist, $"离线测试,工位{(measureBind == null ? "未匹配" : $"{measureBind.WorkPosition}未开启")}"); |
| | |
| | | |
| | | LogAsync(DateTime.Now, EnumHelper.LogLevel.Action, $"离线测试,产品{sn}开始工位{measureBind.WorkPosition}离线检测"); |
| | | MLImageSet imgSet = new MLImageSet(); |
| | | |
| | | imgSet.HImage = new HalconDotNet.HImage(imageFileNames[i]); |
| | | imgSet.PID = sn; |
| | | |
| | | var detectResults = ML.RunMLDetectionSync(imgSet, null, measureBind.DetectionId); |
| | | |
| | | Thread.Sleep(saveimagetime); |
| | | imgSet.HImage?.Dispose(); |
| | | imgSet.HImage = null; |
| | | |
| | | |
| | | |
| | | //var defectFields = M141Config.DefectLocationSettings.FirstOrDefault(u => u.PositionCode == measureBind.WorkPosition); |
| | | |
| | | |
| | | //var list = detectResults.SelectMany(u => u.NetResults.SelectMany(m => m.DetectDetails)).ToList(); |
| | | ////if (list.Count > 0) |
| | | ////{ |
| | | //// //list.ForEach(d => |
| | | //// //{ |
| | | //// // //if (defectFields == null) |
| | | //// // //{ |
| | | //// // // d.Tag = ""; |
| | | //// // //} |
| | | //// // //else |
| | | //// // //{ |
| | | //// // // RectangleF rect = new RectangleF(d.Rect.Point_LU.X, d.Rect.Point_LU.Y, d.Rect.Width, d.Rect.Height); |
| | | //// // // //var rectList = defectFields.Display.RectDict.Where(u => rect.IntersectsWith(u.Value)).ToList(); |
| | | //// // // //if (rectList.Count > 0) |
| | | //// // // //{ |
| | | //// // // // d.Tag = string.Join(" ", rectList.Select(u => u.Key).OrderBy(u => u)); |
| | | //// // // //} |
| | | //// // // //else |
| | | //// // // //{ |
| | | //// // // // d.Tag = ""; |
| | | //// // // //} |
| | | //// // //} |
| | | //// //}); |
| | | ////} |
| | | |
| | | //Bitmap originImage = new Bitmap(imageFileNames[i]); |
| | | //DetectResultSaveExcelAsync(detectResults, sn, originImage, DateTime.Now); |
| | | 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) |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | |
| | | UpdateDefectAsync(defects); |
| | | var defectClass = GetDefectClassFromDefectList(defects); |
| | | UpdateResult(DateTime.Now, p.SN, defectClass.ClassName, ""); |
| | | UpdateResult(DateTime.Now, p.SN, defectClass.ClassName, "", p.ImagePaths); |
| | | |
| | | //产品序号+1 |
| | | //Interlocked.Increment(ref _productIndex); |
| | |
| | | |
| | | |
| | | |
| | | private void UpdateProductResultAsync(ProductModel p) |
| | | private void UpdateProductResultAsync(ProductModel p, string name) |
| | | { |
| | | UpdateProductResult(p, out bool isOK); |
| | | |
| | | _taskFactory.StartNew(() => |
| | | { |
| | | _csvHead = p.GetCSVHead(ref _specHeadList, ref _positionList); |
| | | CSVRecordAsync($"ProductRecord_{DateTime.Now.ToString("yyyyMMdd")}.csv", p.GetCSVData(_specHeadList, _positionList), _csvHead); |
| | | //CSVRecordAsync($"ProductRecord_{DateTime.Now.ToString("yyyyMMdd")}.csv", p.GetCSVData(_specHeadList, _positionList), _csvHead); |
| | | CSVRecordAsync(name, p.GetCSVData(_specHeadList, _positionList), _csvHead); |
| | | //_manager_P_Product.UpdateProductResult(p.ID, p.PID, p.SN, p.Result); |
| | | }); |
| | | |
| | | //连续NG数据记录 |
| | | CheckContinuousNGAlarmAsync(p); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |