using Bro.Common.Base; using Bro.Common.Helper; using Bro.Common.Interface; using Bro.Common.Model; using HalconDotNet; using Lmi3d.GoSdk; using Lmi3d.GoSdk.Messages; using Lmi3d.Zen; using Lmi3d.Zen.Io; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using static Bro.Common.Helper.EnumHelper; namespace Bro.Device.Gocator { [Device("Gocator", "Gocator激光扫描仪", EnumHelper.DeviceAttributeType.Device)] public class GocatorDriver : CameraBase { #region CameraBase public override IOperationConfig GetOperationConfigFromDevice() { var opConfig = new GocatorOperationConfig(); GoSetup setup = sensor.Setup; opConfig.Exposure = (float)setup.GetExposure(GoRole.Main); opConfig.JobName = sensor.DefaultJob; return opConfig; } public override void Snapshot() { GoDataSet dataSet = null; if (IIConfig.IsAsyncMode) { if (!IIConfig.IsHardwareTrigger) { _snapFlag = true; if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout)) { LogAsync(DateTime.Now, $"{Name}获取图像超时", ""); return; } dataSet = _currentData; } } else { try { dataSet = system.ReceiveData(IIConfig.SnapshotTimeout); } catch (Exception ex) { LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage()); return; } } HandleGoData(dataSet); dataSet.Dispose(); } private void HandleGoData(GoDataSet dataSet, GoImageSet imgSet = null) { if (dataSet == null) { return; } for (UInt32 i = 0; i < dataSet.Count; i++) { GoDataMsg dataObj = (GoDataMsg)dataSet.Get(i); switch (dataObj.MessageType) { case GoDataMessageType.Surface: { GoSurfaceMsg surfaceMsg = (GoSurfaceMsg)dataObj; long width = surfaceMsg.Width; long height = surfaceMsg.Length; long bufferSize = width * height; IntPtr bufferPointer = surfaceMsg.Data; float zoomFactor = (float)((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution); int zoomHeight = (int)(zoomFactor * height); IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 2); //IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * 4); //IntPtr zoomPtr = Marshal.AllocHGlobal(zoomHeight * (int)width * (int)IIConfig.ByteNums); //没有插值,默认0 //Parallel.For(0, height, h => // { // CopyMemory((IntPtr)((long)zoomPtr + width * 2 * Math.Floor(h * zoomFactor)), (IntPtr)((long)bufferPointer + width * 2 * h), width * 2); // }); //if (IIConfig.ByteNums == GocatorDataByteNums.Byte2) //{ //使用上一行原有数据 Parallel.For(0, zoomHeight, h => { int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight); CopyMemory((IntPtr)((long)zoomPtr + width * 2 * h), (IntPtr)((long)bufferPointer + width * 2 * originHeightIndex), width * 2); }); //} //else //{ // //使用上一行原有数据 // Parallel.For(0, zoomHeight, h => // { // int originHeightIndex = (int)Math.Floor((double)height * h / (double)zoomHeight); // byte[] rowBuffer = new byte[width * 4]; // Parallel.For(0, width, w => // { // rowBuffer[w * 4 + 2] = Marshal.ReadByte(bufferPointer, (int)(width * 2 * originHeightIndex + w * 2)); // rowBuffer[w * 4 + 3] = Marshal.ReadByte(bufferPointer, (int)(width * 2 * originHeightIndex + w * 2 + 1)); // }); // Marshal.Copy(rowBuffer, 0, (IntPtr)((long)zoomPtr + width * 2 * h), rowBuffer.Length); // }); //} if (imgSet != null) { imgSet.HImage = new HImage(); //imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr); //imgSet.HImage.GenImage1("int4", (int)width, zoomHeight, zoomPtr); //imgSet.HImage.GenImage1(IIConfig.ByteNums == GocatorDataByteNums.Byte2 ? "uint2" : "int4", (int)width, zoomHeight, zoomPtr); imgSet.HImage.GenImage1("int2", (int)width, zoomHeight, zoomPtr); //imgSet.HImage = imgSet.HImage.ConvertImageType("int4"); //imgSet.HImage = imgSet.HImage.ScaleImage(1.0, short.MaxValue + 1.0); //imgSet.HImage = imgSet.HImage.ConvertImageType("uint2"); imgSet.HImage_2 = new HImage(); imgSet.HImage_2.GenImage1("int2", (int)width, zoomHeight, zoomPtr); //imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr); //imgSet.HImage_2.GenImage1("int4", (int)width, zoomHeight, zoomPtr); //imgSet.HImage_2 = new HImage(); //imgSet.HImage_2.GenImage1(IIConfig.ByteNums == GocatorDataByteNums.Byte2 ? "uint2" : "int4", (int)width, zoomHeight, zoomPtr); LaserScanParam para = new LaserScanParam() { Resolution_X = surfaceMsg.XResolution, Resolution_Y = surfaceMsg.YResolution, Resolution_Z = surfaceMsg.ZResolution, Offset_X = surfaceMsg.XOffset, Offset_Y = surfaceMsg.YOffset, Offset_Z = surfaceMsg.ZOffset, Angle_Z = surfaceMsg.ZAngle, }; imgSet.ImageData = JsonConvert.SerializeObject(para); //imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant"); } //var showImage = imgSet.HImage_2.ConvertSignedHImageTo16GrayBitmap(); //showImage.Save($@"D:\SI\{DateTime.Now.ToString("yyyyMMddHHmmss")}.tif", System.Drawing.Imaging.ImageFormat.Tiff); //SaveOriginImage(null, showImage, imgSet.Id); //Marshal.FreeHGlobal(zoomPtr); Generate16GrayImageByPointer((int)width, zoomHeight, zoomPtr, imgSet?.Id).ContinueWith(t => { Marshal.FreeHGlobal(zoomPtr); }); //int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length); //if (imgSet != null) //{ // imgSet.HImage = new HImage(); // imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer); // imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant"); // imgSet.HImage_2 = new HImage(); // imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer); // imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant"); //} //Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id); } break; //case GoDataMessageType.SurfaceIntensity: // { // GoSurfaceIntensityMsg surfaceMsg = (GoSurfaceIntensityMsg)dataObj; // long width = surfaceMsg.Width; // long height = surfaceMsg.Length; // long bufferSize = width * height; // IntPtr bufferPointer = surfaceMsg.Data; // //int zoomHeight = (surfaceMsg.YResolution * (int)surfaceMsg.Length * 10) / surfaceMsg.XResolution; // int zoomHeight = (int)(((double)surfaceMsg.YResolution / (double)surfaceMsg.XResolution) * (double)surfaceMsg.Length); // if (imgSet != null) // { // imgSet.HImage = new HImage(); // imgSet.HImage.GenImage1("uint2", (int)width, (int)height, bufferPointer); // imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant"); // imgSet.HImage_2 = new HImage(); // imgSet.HImage_2.GenImage1("uint2", (int)width, (int)height, bufferPointer); // imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant"); // } // Generate16GrayImageByPointer((int)width, (int)height, bufferPointer, imgSet?.Id); // } // break; } dataObj.Dispose(); } } [MethodImpl(MethodImplOptions.Synchronized)] public override IImageSet Snapshot(IOperationConfig config) { GocatorOperationConfig opConfig = config as GocatorOperationConfig; if (!IIConfig.IsAsyncMode) { if (opConfig.IsOpenConnection) { StartSensor(); } if (!opConfig.IsSnapshotAction) { return null; } } GoImageSet imgSet = new GoImageSet(); InitialImageSet(imgSet, (config as CameraOprerationConfigBase).ImageSaveOption); GoDataSet dataSet = null; if (IIConfig.IsAsyncMode) { if (opConfig.IsSnapshotAction) { if (!IIConfig.IsHardwareTrigger) { _snapFlag = true; if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout)) { LogAsync(DateTime.Now, $"{Name}获取图像超时", ""); return imgSet; } dataSet = _currentData; //dataSet = system.ReceiveData(IIConfig.SnapshotTimeout); } } else { imgSet = null; } } else { if (!opConfig.IsSnapshotAction) { return null; } int reTryTime = 3; do { try { dataSet = system.ReceiveData(IIConfig.SnapshotTimeout); reTryTime = 0; } catch (Exception ex) { reTryTime--; LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage()); if (reTryTime <= 0) { imgSet.HImage = null; dataSet = null; system.ClearData(); } } } while (reTryTime > 0); } if (!IIConfig.IsAsyncMode) { if (!opConfig.IsOpenConnection) { StopSensor(); } } if (dataSet != null) { HandleGoData(dataSet, imgSet); dataSet.Dispose(); if (imgSet.HImage == null) { LogAsync(DateTime.Now, $"{Name}未能获取HImage图像", ""); } } sensor.Flush(); return imgSet; } private void StopSensor() { while (sensor.State == GoState.Busy) { Thread.Sleep(100); } do { try { sensor.Stop(); LogAsync(DateTime.Now, $"传感器状态:{sensor.State.ToString()}", ""); if (sensor.State != GoState.Ready) { Thread.Sleep(100); } else { break; } } catch (Exception ex) { LogAsync(DateTime.Now, $"关闭异常:{ex.GetExceptionMessage()}", ""); Thread.Sleep(100); } } while (true); LogAsync(DateTime.Now, $"传感器关闭成功", ""); } private void StartSensor() { while (sensor.State != GoState.Ready) { Thread.Sleep(10); } do { try { sensor.Start(); LogAsync(DateTime.Now, $"传感器状态:{sensor.State.ToString()}", ""); if (sensor.State != GoState.Running) { Thread.Sleep(100); } else { break; } } catch (Exception ex) { LogAsync(DateTime.Now, $"开启异常:{ex.GetExceptionMessage()}", ""); Thread.Sleep(100); } } while (true); LogAsync(DateTime.Now, $"传感器启动成功", ""); } float _currentExposure = 0; string _currentJob = ""; public override void UploadOperationConfig(IOperationConfig config) { if (config is GocatorOperationConfig opConfig) { if (opConfig.Exposure > 0 && opConfig.Exposure != _currentExposure) { sensor.Setup.SetExposure(GoRole.Main, opConfig.Exposure); _currentExposure = opConfig.Exposure; } if (!string.IsNullOrWhiteSpace(opConfig.JobName) && _currentJob != opConfig.JobName) { LogAsync(DateTime.Now, $"{Name}切换当前任务为{opConfig.JobName}", ""); sensor.CopyFile(_currentJob, "_live.job"); bool isChanged = false; sensor.LoadedJob(ref _currentJob, ref isChanged); LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", ""); } sensor.Flush(); } } protected override void Init() { KApiLib.Construct(); GoSdkLib.Construct(); system = new GoSystem(); if (IIConfig.IsUseAccelerator) { accelerator = new GoAccelerator(); } KIpAddress ip = KIpAddress.Parse(IConfig.CameraIP); if (IIConfig.IsUseAccelerator) { accelerator.Start(); } sensor = system.FindSensorByIpAddress(ip); if (IIConfig.IsUseAccelerator) { accelerator.Attach(sensor); } sensor.Connect(); if (IIConfig.IsUseAccelerator) { sensor.Flush(); accelerator.Start(); } sensor.Setup.ScanMode = GoMode.Surface; system.EnableData(true); if (IIConfig.IsAsyncMode) { system.SetDataHandler(onData); } _currentExposure = (float)sensor.Setup.GetExposure(GoRole.Main); if (IIConfig.DefaultExposure > 0 && _currentExposure != IIConfig.DefaultExposure) { sensor.Setup.SetExposure(GoRole.Main, IIConfig.DefaultExposure); _currentExposure = (float)sensor.Setup.GetExposure(GoRole.Main); } bool isChanged = false; sensor.LoadedJob(ref _currentJob, ref isChanged); LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", ""); if (!string.IsNullOrWhiteSpace(IIConfig.DefaultJob) && IIConfig.DefaultJob != _currentJob) { sensor.CopyFile(IIConfig.DefaultJob, "_live.job"); //_currentJob = IIConfig.DefaultJob; sensor.LoadedJob(ref _currentJob, ref isChanged); LogAsync(DateTime.Now, $"{Name}当前任务{_currentJob}", ""); } sensor.Flush(); } protected override void Start() { base.Start(); //if (sensor.State != GoState.Ready) //{ // system.Start(); //} if (IIConfig.IsAsyncMode) { //sensor.Start(); StartSensor(); } //else //{ // //if (sensor.State == GoState.Ready) // //{ // // sensor.Stop(); // //} // StopSensor(); //} } protected override void Stop() { base.Stop(); if (IIConfig.IsAsyncMode) { StopSensor(); } if (IIConfig.IsUseAccelerator) { accelerator.Stop(); } sensor.Disconnect(); } protected override void Pause() { } protected override void Resume() { } #endregion GoSystem system = null; GoAccelerator accelerator = null; GoSensor sensor = null; public GocatorInitialConfig IIConfig { get => InitialConfig as GocatorInitialConfig; } volatile bool _snapFlag = false; readonly AutoResetEvent _snapHandle = new AutoResetEvent(false); GoDataSet _currentData = null; /// /// 异步模式获取数据 /// /// private void onData(KObject data) { LogAsync(DateTime.Now, $"扫描图像输出", ""); GoDataSet dataSet = (GoDataSet)data; if (IIConfig.IsHardwareTrigger) { GoImageSet imgSet = new GoImageSet(); InitialImageSet(imgSet, IConfig.ImageSaveOption); HandleGoData(dataSet, imgSet); if (imgSet.HImage != null) { OnHImageOutput?.BeginInvoke(this, imgSet.HImage, imgSet.Id, null, null); } else { LogAsync(DateTime.Now, $"{Name}获取HImage失败", ""); } } else { //if (_snapFlag) { _snapFlag = false; _currentData = dataSet.Clone(); _currentData = dataSet; _snapHandle.Set(); } } dataSet.Dispose(); } #region 重写图片保存操作 public override async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId) { Task.Run(() => { OnImageUpdated?.Invoke(this, showImage, imgSetId); }); GoImageSet set = _imageSetList[imgSetId] as GoImageSet; if (set == null) return; await Task.Run(() => { lock (set.SaveLock) { if (set.ImageSaveOption.IsSaveOriginImage && !set.IsOriginSaved) { string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, "Origin"); try { //SaveImageByNameAndType(map, set.Id, set.ImageSaveOption.ImageFormat, imgDir); string filePath = Path.Combine(imgDir, $"{set.Id}.tif"); set.HImage_2.WriteImage("tiff", 0, filePath); set.HImage_2.Dispose(); set.HImage_2 = null; } catch (Exception ex) { LogAsync(DateTime.Now, $"{set.Id}原图保存失败", ex.GetExceptionMessage()); } } set.IsOriginSaved = true; ClearImageSet(set); } }); } /// /// 保存特定类型图片,例如NG图片 /// /// 图片类型说明 例如“NG” /// 图片ID public override async void SaveSelectedImage(string prefix, string imgSetId) { await Task.Run(() => { GoImageSet set = _imageSetList[imgSetId] as GoImageSet; if (set == null) return; lock (set.SaveLock) { if (set.ImageSaveOption.AddtionalSaveType.Contains(prefix) && !set.IsAddtionalSaved) { string imgDir = CheckImageDirectory(set.ImageSaveOption.ImageSaveSubDirectory, prefix); try { string filePath = Path.Combine(imgDir, $"{set.Id}.tif"); set.HImage_2.WriteImage("tiff", 0, filePath); } catch (Exception ex) { LogAsync(DateTime.Now, $"{set.Id}{prefix}图片保存失败", ex.GetExceptionMessage()); } } set.IsAddtionalSaved = true; ClearImageSet(set); } }); } //public override void ClearImageSet(IImageSet set) //{ // if (set.IsOriginSaved && set.IsFitSaved && set.IsAddtionalSaved) // { // (set as GoImageSet).HImage_2?.Dispose(); // (set as GoImageSet).HImage_2 = null; // } // base.ClearImageSet(set); //} #endregion } public class GoImageSet : ImageSet { public HImage HImage_2 { get; set; } public override void Dispose() { //HImage_2?.Dispose(); //HImage_2 = null; base.Dispose(); } } }