using Bro.Common.Base;
using Bro.Common.Helper;
using Bro.Common.Interface;
using HalconDotNet;
using Lmi3d.GoSdk;
using Lmi3d.GoSdk.Messages;
using Lmi3d.Zen;
using Lmi3d.Zen.Io;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
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);
}
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);
//没有插值,默认0
//Parallel.For(0, height, h =>
// {
// CopyMemory((IntPtr)((long)zoomPtr + width * 2 * Math.Floor(h * zoomFactor)), (IntPtr)((long)bufferPointer + width * 2 * h), width * 2);
// });
//使用上一行原有数据
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);
});
if (imgSet != null)
{
imgSet.HImage = new HImage();
imgSet.HImage.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
//imgSet.HImage = imgSet.HImage.ZoomImageSize((int)width, zoomHeight, "constant");
imgSet.HImage_2 = new HImage();
imgSet.HImage_2.GenImage1("uint2", (int)width, zoomHeight, zoomPtr);
//imgSet.HImage_2 = imgSet.HImage_2.ZoomImageSize((int)width, zoomHeight, "constant");
}
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;
}
}
}
public override IImageSet Snapshot(IOperationConfig config)
{
if (!IIConfig.IsAsyncMode)
{
if (config is GocatorOperationConfig opConfig)
{
if (opConfig.IsOpenConnection)
{
system.Start();
}
else
{
system.Stop();
}
if (!opConfig.IsSnapshotAction)
{
return null;
}
}
}
GoImageSet imgSet = new GoImageSet();
InitialImageSet(imgSet, (config as CameraOprerationConfigBase).ImageSaveOption);
GoDataSet dataSet = null;
if (IIConfig.IsAsyncMode)
{
if (!IIConfig.IsHardwareTrigger)
{
_snapFlag = true;
if (!_snapHandle.WaitOne(IIConfig.SnapshotTimeout))
{
LogAsync(DateTime.Now, $"{Name}获取图像超时", "");
return null;
}
dataSet = _currentData;
}
}
else
{
try
{
dataSet = system.ReceiveData(IIConfig.SnapshotTimeout);
}
catch (Exception ex)
{
LogAsync(DateTime.Now, $"{Name}获取图像异常", ex.GetExceptionMessage());
return null;
}
}
HandleGoData(dataSet, imgSet);
if (imgSet.HImage == null)
{
LogAsync(DateTime.Now, $"{Name}未能获取HImage图像", "");
}
return imgSet;
}
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)
{
_currentJob = sensor.DefaultJob = opConfig.JobName;
}
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);
}
_currentJob = sensor.DefaultJob;
if (!string.IsNullOrWhiteSpace(IIConfig.DefaultJob) && _currentJob != IIConfig.DefaultJob)
{
//_currentJob = sensor.DefaultJob = IIConfig.DefaultJob;
string currentJob = IIConfig.DefaultJob;
bool isChanged = false;
sensor.LoadedJob(ref currentJob, ref isChanged);
if (!isChanged)
{
throw new ProcessException($"{Name}未成功切换至任务{IIConfig.DefaultJob}");
}
}
sensor.Flush();
}
protected override void Start()
{
base.Start();
if (IIConfig.IsAsyncMode)
system.Start();
}
protected override void Stop()
{
base.Stop();
if (IIConfig.IsAsyncMode)
system.Stop();
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 ManualResetEvent _snapHandle = new ManualResetEvent(false);
GoDataSet _currentData = null;
///
/// 异步模式获取数据
///
///
private void onData(KObject data)
{
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();
_snapHandle.Set();
}
}
}
#region 重写图片保存操作
public override async void SaveOriginImage(Bitmap map, Bitmap showImage, string imgSetId)
{
Task.Run(() =>
{
OnImageUpdated?.Invoke(this, showImage, imgSetId);
});
GoImageSet set = _imageSetList.FirstOrDefault(u => u.Id == imgSetId) as GoImageSet;
if (set == null)
return;
set.Image = map;
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);
}
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.FirstOrDefault(u => u.Id == 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);
while (set.Image == null)
{
Thread.Sleep(50);
}
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);
}
});
}
#endregion
}
public class GoImageSet : ImageSet
{
public HImage HImage_2 { get; set; }
public override void Dispose()
{
base.Dispose();
HImage_2?.Dispose();
HImage_2 = null;
}
}
}