| | |
| | | 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() |
| | | { |
| | | throw new NotImplementedException(); |
| | | 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() |
| | | { |
| | | throw new NotImplementedException(); |
| | | 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_2 = imgSet.HImage.Clone(); |
| | | //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"); |
| | | } |
| | | |
| | | 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) |
| | | { |
| | | 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, $"传感器启动成功", ""); |
| | | } |
| | | |
| | | 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 null; |
| | | } |
| | | |
| | | dataSet = _currentData; |
| | | } |
| | | } |
| | | 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) |
| | | { |
| | | 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, $"传感器关闭成功", ""); |
| | | } |
| | | } |
| | | |
| | | sensor.Flush(); |
| | | |
| | | if (dataSet != null) |
| | | { |
| | | HandleGoData(dataSet, imgSet); |
| | | |
| | | dataSet.Dispose(); |
| | | |
| | | if (imgSet.HImage == null) |
| | | { |
| | | LogAsync(DateTime.Now, $"{Name}未能获取HImage图像", ""); |
| | | } |
| | | } |
| | | |
| | | return imgSet; |
| | | } |
| | | |
| | | float _currentExposure = 0; |
| | | string _currentJob = ""; |
| | | public override void UploadOperationConfig(IOperationConfig config) |
| | | { |
| | | throw new NotImplementedException(); |
| | | 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() |
| | | { |
| | | throw new NotImplementedException(); |
| | | 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(); |
| | | } |
| | | else |
| | | { |
| | | //if (sensor.State == GoState.Ready) |
| | | { |
| | | sensor.Stop(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected override void Stop() |
| | | { |
| | | base.Stop(); |
| | | |
| | | if (IIConfig.IsAsyncMode) |
| | | system.Stop(); |
| | | |
| | | if (IIConfig.IsUseAccelerator) |
| | | { |
| | | accelerator.Stop(); |
| | | } |
| | | |
| | | sensor.Disconnect(); |
| | | } |
| | | |
| | | protected override void Pause() |
| | | { |
| | | throw new NotImplementedException(); |
| | | } |
| | | |
| | | protected override void Resume() |
| | | { |
| | | throw new NotImplementedException(); |
| | | } |
| | | #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; |
| | | /// <summary> |
| | | /// 异步模式获取数据 |
| | | /// </summary> |
| | | /// <param name="data"></param> |
| | | 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<GoDataSet>(); |
| | | _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; |
| | | |
| | | 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); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | /// <summary> |
| | | /// 保存特定类型图片,例如NG图片 |
| | | /// </summary> |
| | | /// <param name="prefix">图片类型说明 例如“NG”</param> |
| | | /// <param name="imgSetId">图片ID</param> |
| | | 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); |
| | | |
| | | 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); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | //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() |
| | | { |
| | | base.Dispose(); |
| | | |
| | | HImage_2?.Dispose(); |
| | | HImage_2 = null; |
| | | } |
| | | } |
| | | } |