汽车
大恒相机(大恒相机(Galaxy )SDK C# 取图完整代码,可直接使用)

海康相机SDK取图参照:海康相机(HIKROBOT)SDK C# 取图完整代码

以下是基于大恒相机(Galaxy ) SDK(实现的相机搜索、连接、采图、参数设置等功能的完整代码,代码风格、架构,同时融入了资源优化、逻辑严谨性等最佳实践:

using Cognex.VisionPro;using GxIAPINET;using System;using System.Collections.Generic;using System.ComponentModel;using System.Diagnostics;using System.IO;using System.Linq;using System.Runtime.InteropServices;using System.Text;using System.Threading;using System.Threading.Tasks;namespace DAL.Camera{    [Category("大恒相机")]    [DisplayName("大恒相机")]    [Serializable]    public class CamerasDaheng : Camerasbase    {        #region 私有成员(严格遵循官方文档数据类型定义)        [NonSerialized]        private IGXDevice _gxDevice = null; // 设备对象(文档6.5节)        [NonSerialized]        private IGXStream _gxStream = null; // 流对象(文档6.14节)        [NonSerialized]        private IGXFeatureControl _remoteFeatureCtrl = null; // 远端设备属性控制器(文档6.6节)        [NonSerialized]        private IGXFeatureControl _streamFeatureCtrl = null; // 流层属性控制器(文档6.14.9节)        [NonSerialized]        private Stopwatch _stopwatch = new Stopwatch();        [NonSerialized]        private List<IGXDeviceInfo> _deviceInfoList = new List<IGXDeviceInfo>(); // 设备信息列表(文档6.4节)        private uint _payloadSize = 0; // 有效载荷大小(文档6.14.14节)        private uint _rowStep = 0; // 行步长        private bool _isGrabbing = false; // 是否正在抓图        private bool _disposed = false; // 是否已释放资源        private IGXDeviceInfo _curDeviceInfo = null; // 当前设备信息(文档6.4节)        // 常量定义(严格对应官方文档枚举值)        private const int TRIGGER_SOURCE_SOFTWARE = 1; // 软触发(文档2.11.3节)        private const int TRIGGER_SOURCE_LINE0 = 0;    // Line0触发(文档2.10.6节)        private const int TRIGGER_ACTIVATION_RISING = 0; // 上升沿(文档2.10.6节)        private const int TRIGGER_ACTIVATION_FALLING = 1; // 下降沿(文档2.10.6节)        private const int TRIGGER_MODE_OFF = 0; // 触发模式关闭(内触发)        private const int TRIGGER_MODE_ON = 1;  // 触发模式开启(外触发/软触发)        private const string ACQUISITION_MODE_ConTINUOUS = "Continuous"; // 连续采集模式(文档2.10.6节)        private const int TIMEOUT_MILLISEConDS = 1000; // 超时时间(文档2.11.2节)        private const int BUFFER_COUNT = 10; // 采集缓存个数(文档2.11.4节,建议≥3)        #endregion        #region 构造函数与析构函数        public CamerasDaheng() : base()        {            try            {                // 初始化SDK(文档2.3节)                IGXFactory.GetInstance().Init();                Log.Addlog(2, "大恒相机SDK初始化成功");            }            catch (CGalaxyException ex)            {                Log.Error($"SDK初始化失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                throw new Exception($"SDK初始化失败:{ex.Message}");            }        }        ~CamerasDaheng()        {            Dispose(false);        }        #endregion        #region 核心方法实现(遵循官方文档编程流程)        /// <summary>        /// 搜索相机(文档2.5节,全网枚举)        /// </summary>        public override List<CamerasInfo> SearchCameras()        {            List<CamerasInfo> camInfoList = new List<CamerasInfo>();            try            {                _deviceInfoList.Clear();                // 枚举所有设备(千兆网+USB3.0,超时200ms)                IGXFactory.GetInstance().UpdateAllDeviceList(200, _deviceInfoList);                if (_deviceInfoList.Count == 0)                {                    Log.ShowErrorDialog("未找到任何大恒相机设备");                    return camInfoList;                }                // 遍历设备列表(文档6.4节,IGXDeviceInfo接口)                foreach (var deviceInfo in _deviceInfoList)                {                    CamerasInfo camInfo = new CamerasInfo();                    string serialNo = deviceInfo.GetSN();                    string modelName = deviceInfo.GetModelName();                    string vendorName = deviceInfo.GetVendorName();                    string deviceClass = GetDeviceClassDesc(deviceInfo.GetDeviceClass());                    // 构建相机名称(文档6.4.4节)                    camInfo.m_CamName = $"Daheng({deviceClass}): {vendorName} {modelName} ({serialNo})";                    camInfo.m_ExtInfo = deviceInfo;                    camInfo.m_SerialNO = serialNo;                    camInfo.m_MaskName = serialNo;                    camInfoList.Add(camInfo);                }            }            catch (CGalaxyException ex)            {                Log.Error($"相机搜索失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }            catch (Exception ex)            {                Log.Error($"相机搜索异常:{ex.Message}");            }            return camInfoList;        }        /// <summary>        /// 连接相机(文档2.9节,按序列号打开)        /// </summary>        public override bool ConnectDev()        {            try            {                base.ConnectDev();                DisConnectDev(); // 先断开已连接设备                if (string.IsNullOrEmpty(mSerialNo))                {                    Log.Error("相机序列号不能为空");                    return false;                }                // 查找目标设备                if (!FindCameraBySN(mSerialNo))                {                    Log.Error($"未找到序列号为{mSerialNo}的大恒相机");                    return false;                }                // 打开设备(独占模式,文档6.1.9节)                _gxDevice = IGXFactory.GetInstance().OpenDeviceBySN(mSerialNo, GX_ACCESS_MODE.GX_ACCESS_EXCLUSIVE);                if (_gxDevice == null)                {                    Log.Error("打开相机设备失败");                    return false;                }                // 获取属性控制器(文档6.5.4/6.5.5节)                _remoteFeatureCtrl = _gxDevice.GetRemoteFeatureControl();                if (_remoteFeatureCtrl == null)                {                    Log.Error("获取远端设备属性控制器失败");                    DisConnectDev();                    return false;                }                // 打开流对象(文档6.5.3节,流索引0)                if (_gxDevice.GetStreamCount() > 0)                {                    _gxStream = _gxDevice.OpenStream(0);                    if (_gxStream == null)                    {                        Log.Error("创建流对象失败");                        DisConnectDev();                        return false;                    }                    _streamFeatureCtrl = _gxStream.GetFeatureControl();                }                else                {                    Log.Error("相机无可用流通道");                    DisConnectDev();                    return false;                }                // 千兆网相机优化:设置最优包长(文档2.11.1节)                SetGigEOptimalPacketSize();                // 设置采集缓存个数(文档2.11.4节,建议≥3)                _gxStream.SetAcqusitionBufferNumber(BUFFER_COUNT);                // 获取相机基础参数                GetImageSizeAndPayload();                // 设置默认参数                SetSetting();                // 注册回调函数(文档2.11.3节)                _gxStream.RegisterCaptureCallback(this, frameCallbackFunc);                // 开始抓图                StartGrab();                mConnected = true;                Log.Addlog(2, $"大恒相机({mSerialNo})连接成功");                return true;            }            catch (CGalaxyException ex)            {                Log.Error($"相机连接失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                DisConnectDev();            }            catch (Exception ex)            {                Log.Error($"相机连接异常:{ex.Message}");                DisConnectDev();            }            return false;        }        /// <summary>        /// 断开相机(文档2.9节,释放资源流程)        /// </summary>        public override void DisConnectDev()        {            try            {                // 停止抓图                if (_isGrabbing)                {                    StopGrab();                }                // 注销回调函数(文档6.14.4节)                _gxStream?.UnregisterCaptureCallback();                // 关闭流对象(文档6.14.12节)                if (_gxStream != null)                {                    _gxStream.Close();                    _gxStream = null;                }                // 关闭设备(文档6.5.19节)                if (_gxDevice != null)                {                    _gxDevice.Close();                    _gxDevice = null;                }                // 释放属性控制器                _remoteFeatureCtrl = null;                _streamFeatureCtrl = null;                mConnected = false;                Log.Addlog(2, "大恒相机已断开连接");            }            catch (CGalaxyException ex)            {                Log.Error($"断开连接失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }            catch (Exception ex)            {                Log.Error($"断开连接异常:{ex.Message}");            }        }        /// <summary>        /// 开始抓图(文档2.11.3节,先开启流采集再发送开采命令)        /// </summary>        public override void StartGrab()        {            try            {                if (_gxStream == null || _isGrabbing)                {                    return;                }                // 开启流层采集(文档6.14.1节)                _gxStream.StartGrab();                // 发送开采命令(文档2.10.6.7节)                var startCmd = _remoteFeatureCtrl.GetCommandFeature("AcquisitionStart");                startCmd?.Execute();                _isGrabbing = true;                Log.Addlog(2, "大恒相机开始抓图");            }            catch (CGalaxyException ex)            {                Log.Error($"开始抓图失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 停止抓图(文档2.11.3节)        /// </summary>        public override void StopGrab()        {            try            {                if (_gxStream == null || !_isGrabbing)                {                    return;                }                // 发送停采命令(文档2.10.6.7节)                var stopCmd = _remoteFeatureCtrl.GetCommandFeature("AcquisitionStop");                stopCmd?.Execute();                // 停止流层采集(文档6.14.2节)                _gxStream.StopGrab();                // 清空采集队列(文档6.14.10节)                _gxStream.FlushQueue();                _isGrabbing = false;                Log.Addlog(2, "大恒相机已停止抓图");            }            catch (CGalaxyException ex)            {                Log.Error($"停止抓图失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 连续采图模式(内触发,文档2.11.3节)        /// </summary>        public override void ContinuesMode()        {            try            {                if (!mConnected)                {                    Log.Error("相机未连接,无法切换连续模式");                    return;                }                SetTriggerMode(TrigMode.内触发);                Log.Addlog(2, "大恒相机已切换为连续采图模式");            }            catch (Exception ex)            {                Log.Error($"切换连续模式异常:{ex.Message}");            }        }        /// <summary>        /// 采集图像(软触发,文档2.11.2节)        /// </summary>        public override async Task<bool> CaptureImageAsync(bool byHand)        {            bool result = false;            try            {                if (!mConnected)                {                    Log.Error("相机未连接,无法采集图像");                    return false;                }                EventWait.Reset();                // 设置软触发模式                if (!SetTriggerMode(TrigMode.软触发))                {                    Log.Error("设置软触发模式失败");                    return false;                }                // 发送软触发命令(文档2.10.6.7节)                var trigCmd = _remoteFeatureCtrl.GetCommandFeature("TriggerSoftware");                trigCmd?.Execute();                // 异步延迟,避免线程阻塞                await Task.Delay(10);                // 等待采集完成                result = EventWait.WaitOne(TIMEOUT_MILLISECONDS);            }            catch (CGalaxyException ex)            {                Log.Error($"采集图像失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                result = false;            }            catch (Exception ex)            {                Log.Error($"采集图像异常:{ex.Message}");                result = false;            }            return result;        }        /// <summary>        /// 加载参数配置(文档2.14节)        /// </summary>        public override void LoadSetting(string filePath)        {            try            {                if (!mConnected || !File.Exists(filePath))                {                    Log.Error("相机未连接或配置文件不存在");                    return;                }                // 导入配置文件(文档6.5.16节)                _gxDevice.importConfigFile(filePath);                Log.Addlog(2, $"成功加载配置文件:{filePath}");                // 重新获取参数                GetSetting();            }            catch (CGalaxyException ex)            {                Log.Error($"加载配置失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 保存参数配置(文档2.14节)        /// </summary>        public override void SaveSetting(string filePath)        {            try            {                if (!mConnected)                {                    Log.Error("相机未连接,无法保存配置");                    return;                }                // 导出配置文件(文档6.5.15节)                _gxDevice.ExportConfigFile(filePath);                Log.Addlog(2, $"成功保存配置文件:{filePath}");            }            catch (CGalaxyException ex)            {                Log.Error($"保存配置失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 设置相机参数(文档2.10节)        /// </summary>        public override void SetSetting()        {            try            {                if (!mConnected)                {                    return;                }                // 设置采集模式为连续(文档2.10.6.5节)                var acquisitionMode = _remoteFeatureCtrl.GetEnumFeature("AcquisitionMode");                if (acquisitionMode != null && _remoteFeatureCtrl.IsWritable("AcquisitionMode"))                {                    acquisitionMode.SetValue(ACQUISITION_MODE_CONTINUOUS);                }                // 设置触发模式                SetTriggerMode((TrigMode)mTrigMode);                // 设置曝光时间(文档2.10.6.3节)                var exposeFeature = _remoteFeatureCtrl.GetFloatFeature("ExposureTime");                if (exposeFeature != null && _remoteFeatureCtrl.IsWritable("ExposureTime"))                {                    exposeFeature.SetValue(mExposeTime);                }                // 设置增益(文档2.10.6.3节)                var gainFeature = _remoteFeatureCtrl.GetFloatFeature("Gain");                if (gainFeature != null && _remoteFeatureCtrl.IsWritable("Gain"))                {                    gainFeature.SetValue(mGain);                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置参数失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 获取相机参数(文档2.10节)        /// </summary>        public override void GetSetting()        {            try            {                if (!mConnected)                {                    return;                }                // 获取曝光时间(文档2.10.6.3节)                _remoteFeatureCtrl = _gxDevice.GetRemoteFeatureControl(); // 获取属性控制器                var exposeFeature = _remoteFeatureCtrl.GetFloatFeature("ExposureTime");                if (exposeFeature != null && _remoteFeatureCtrl.IsReadable("ExposureTime"))                {                    mExposeTime = (float)exposeFeature.GetValue();                }                // 获取增益(文档2.10.6.3节)                var gainFeature = _remoteFeatureCtrl.GetFloatFeature("Gain");                if (gainFeature != null && _remoteFeatureCtrl.IsReadable("Gain"))                {                    mGain = (float)gainFeature.GetValue();                }                // 获取帧率(文档2.10.6.3节)                var frameRateFeature = _remoteFeatureCtrl.GetFloatFeature("AcquisitionframeRate");                if (frameRateFeature != null && _remoteFeatureCtrl.IsReadable("AcquisitionframeRate"))                {                    mframerate = frameRateFeature.GetValue().ToString("F2");                }                // 获取触发模式(文档2.10.6.5节)                var trigModeFeature = _remoteFeatureCtrl.GetEnumFeature("TriggerMode");                if (trigModeFeature != null && _remoteFeatureCtrl.IsReadable("TriggerMode"))                {                    mTrigMode = trigModeFeature.GetEnumValue().nCurValue == TRIGGER_MODE_OFF                        ? TrigMode.内触发                        : TrigMode.软触发;                }                // 获取图像宽高(文档2.10.6.2节)                // 正确:通过IGXFeatureControl调用IsWritable()判断属性是否可写                var widthFeature = _remoteFeatureCtrl.GetIntFeature("Width");                if (widthFeature != null && _remoteFeatureCtrl.IsReadable("Width"))                {                    mWidth = (int)widthFeature.GetValue();                    mWidthMax = (int)widthFeature.GetMax();                }                var heightFeature = _remoteFeatureCtrl.GetIntFeature("Height");                if (heightFeature != null && _remoteFeatureCtrl.IsReadable("Height"))                {                    mHeight = (int)heightFeature.GetValue();                    mHeightMax = (int)heightFeature.GetMax();                }            }            catch (CGalaxyException ex)            {                Log.Error($"获取参数失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 相机参数变更(文档2.10节)        /// </summary>        public override void CameraChanged(ChangType changTyp)        {            try            {                if (!mConnected)                {                    return;                }                switch (changTyp)                {                    case ChangType.增益:                        SetGain(mGain);                        break;                    case ChangType.曝光:                        SetExposureTime(mExposeTime);                        break;                    case ChangType.宽度:                        SetImageWidth(mWidth);                        break;                    case ChangType.高度:                        SetImageHeight(mHeight);                        break;                    case ChangType.触发:                        SetTriggerMode((TrigMode)mTrigMode);                        break;                }            }            catch (Exception ex)            {                Log.Error($"参数变更异常:{ex.Message}");            }        }        /// <summary>        /// 设置触发模式(文档2.10.6.5节)        /// </summary>        public override bool SetTriggerMode(TrigMode mode)        {            try            {                if (!mConnected)                {                    return false;                }                // 设置触发模式开关                var trigModeFeature = _remoteFeatureCtrl.GetEnumFeature("TriggerMode");                if (trigModeFeature == null || !_remoteFeatureCtrl.IsWritable("TriggerMode"))                {                    Log.Error("触发模式功能不支持");                    return false;                }                trigModeFeature.SetEnumValue(mode == TrigMode.内触发 ? TRIGGER_MODE_OFF : TRIGGER_MODE_ON);                // 设置触发源和触发方式                var trigSourceFeature = _remoteFeatureCtrl.GetEnumFeature("TriggerSource");                var trigActivationFeature = _remoteFeatureCtrl.GetEnumFeature("TriggerActivation");                if (trigSourceFeature == null || !_remoteFeatureCtrl.IsWritable("TriggerSource"))                {                    Log.Error("触发源功能不支持");                    return false;                }                switch (mode)                {                    case TrigMode.内触发:                        break;                    case TrigMode.软触发:                        trigSourceFeature.SetEnumValue(TRIGGER_SOURCE_SOFTWARE);                        break;                    case TrigMode.上升沿:                        trigSourceFeature.SetEnumValue(TRIGGER_SOURCE_LINE0);                        if (trigActivationFeature != null && _remoteFeatureCtrl.IsWritable("TriggerActivation"))                        {                            trigActivationFeature.SetEnumValue(TRIGGER_ACTIVATION_RISING);                        }                        break;                    case TrigMode.下降沿:                        trigSourceFeature.SetEnumValue(TRIGGER_SOURCE_LINE0);                        if (trigActivationFeature != null && _remoteFeatureCtrl.IsWritable("TriggerActivation"))                        {                            trigActivationFeature.SetEnumValue(TRIGGER_ACTIVATION_FALLING);                        }                        break;                }                return true;            }            catch (CGalaxyException ex)            {                Log.Error($"设置触发模式失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                return false;            }        }        #endregion        #region 辅助方法(严格遵循官方文档API使用规范)        /// <summary>        /// 根据序列号查找相机(文档6.4节)        /// </summary>        private bool FindCameraBySN(string serialNo)        {            try            {                _deviceInfoList.Clear();                IGXFactory.GetInstance().UpdateAllDeviceList(200, _deviceInfoList);                foreach (var deviceInfo in _deviceInfoList)                {                    if (deviceInfo.GetSN().Equals(serialNo, StringComparison.OrdinalIgnoreCase))                    {                        _curDeviceInfo = deviceInfo;                        return true;                    }                }                return false;            }            catch (CGalaxyException ex)            {                Log.Error($"查找相机失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                return false;            }        }        /// <summary>        /// 获取设备类型描述(文档3.3节,GX_DEVICE_CLASS_LIST)        /// </summary>        private string GetDeviceClassDesc(GX_DEVICE_CLASS_LIST deviceClass)        {            string device = "";            switch (deviceClass)            {                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_UNKNOWN:                    device = "Unknown";                    break;                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_USB2:                    device = "GX_DEVICE_CLASS_USB2";                    break;                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV:                    device = "GEV";                    break;                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_U3V:                    device = "U3V";                    break;                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_SMART:                    device = "MART";                    break;                case GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_CXP:                    device = "CXP";                    break;                default:                    device = "Unknown";                    break;            }            return device;        }        /// <summary>        /// 千兆网相机设置最优包长(文档2.11.1节)        /// </summary>        private void SetGigEOptimalPacketSize()        {            try            {                if (_curDeviceInfo.GetDeviceClass() != GX_DEVICE_CLASS_LIST.GX_DEVICE_CLASS_GEV)                {                    return;                }                // 检查是否支持GevSCPSPacketSize功能                if (_remoteFeatureCtrl.IsImplemented("GevSCPSPacketSize") && _remoteFeatureCtrl.IsWritable("GevSCPSPacketSize"))                {                    // 获取最优包长                    uint optimalPacketSize = _gxStream.GetOptimalPacketSize();                    // 设置包长                    var packetSizeFeature = _remoteFeatureCtrl.GetIntFeature("GevSCPSPacketSize");                    packetSizeFeature?.SetValue(optimalPacketSize);                    Log.Addlog(2, $"千兆网相机最优包长设置为:{optimalPacketSize}");                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置最优包长失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 获取图像宽高和有效载荷(文档6.14.14节)        /// </summary>        private void GetImageSizeAndPayload()        {            try            {                // 获取有效载荷大小                _payloadSize = (uint)_gxStream.GetPayloadSize();                // 获取图像宽高                var widthFeature = _remoteFeatureCtrl.GetIntFeature("Width");                var heightFeature = _remoteFeatureCtrl.GetIntFeature("Height");                if (widthFeature != null && heightFeature != null)                {                    mWidth = (int)widthFeature.GetValue();                    mHeight = (int)heightFeature.GetValue();                    mWidthMax = (int)widthFeature.GetMax();                    mHeightMax = (int)heightFeature.GetMax();                }                // 计算行步长(文档2.11.5节,根据像素格式)                var pixelFormatFeature = _remoteFeatureCtrl.GetEnumFeature("PixelFormat");                if (pixelFormatFeature != null)                {                    GX_PIXEL_FORMAT_ENTRY pixelFormat = (GX_PIXEL_FORMAT_ENTRY)pixelFormatFeature.GetEnumValue().nCurValue;                    _rowStep = (uint)mWidth * GetPixelByteCount(pixelFormat);                }            }            catch (CGalaxyException ex)            {                Log.Error($"获取图像参数失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 获取像素格式对应的字节数(文档3.6节,GX_PIXEL_FORMAT_ENTRY)        /// </summary>        private uint GetPixelByteCount(GX_PIXEL_FORMAT_ENTRY pixelFormat)        {            uint format = 0;            switch (pixelFormat)            {                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_UNDEFINED:                    format = 0;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8:                    format = 1;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8_SIGNED:                    format = 1;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10:                    format = 2;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_P:                    format = 2;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12:                    format = 3;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_P:                    format = 3;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14:                    format = 4;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14_P:                    format = 4;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO16:                    format = 5;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG8:                    format = 6;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10:                    format = 7;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_P:                    format = 7;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12:                    format = 8;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_P:                    format = 8;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14:                    format = 9;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14_P:                    format = 9;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG16:                    format = 10;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB8:                    format = 11;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10:                    format = 12;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_P:                    format = 12;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12:                    format = 13;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_P:                    format = 13;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14:                    format = 14;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14_P:                    format = 14;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB16:                    format = 15;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR8:                    format = 16;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10:                    format = 17;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_P:                    format = 17;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12:                    format = 18;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_P:                    format = 18;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14:                    format = 19;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14_P:                    format = 19;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR16:                    format = 20;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGBA8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB10_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB12_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB16_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGRA8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_R8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_G8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_B8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_ABC32F:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_ABC32F_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV422_8_UYVY:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV420_8_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_ARGB8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_ABGR8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_I16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_S16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_I16_S16:                    break;                default:                    break;            }            return format;        }        /// <summary>        /// 设置增益(文档2.10.6.3节)        /// </summary>        private void SetGain(float gain)        {            try            {                var gainFeature = _remoteFeatureCtrl.GetFloatFeature("Gain");                if (gainFeature != null && _remoteFeatureCtrl.IsWritable("Gain"))                {                    gainFeature.SetValue(gain);                    mGain = gain;                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置增益失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 设置曝光时间(文档2.10.6.3节)        /// </summary>        private void SetExposureTime(float exposeTime)        {            try            {                var exposeFeature = _remoteFeatureCtrl.GetFloatFeature("ExposureTime");                if (exposeFeature != null && _remoteFeatureCtrl.IsWritable("ExposureTime"))                {                    exposeFeature.SetValue(exposeTime);                    mExposeTime = exposeTime;                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置曝光时间失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 设置图像宽度(文档2.10.6.2节)        /// </summary>        private void SetImageWidth(int width)        {            try            {                if (width <= 0 || width > mWidthMax)                {                    Log.Error($"宽度值{width}超出范围(0-{mWidthMax})");                    return;                }                // 正确:通过IGXFeatureControl调用IsWritable()判断属性是否可写                IGXFeatureControl featureCtrl = _gxDevice.GetRemoteFeatureControl(); // 获取属性控制器                var widthFeature = _remoteFeatureCtrl.GetIntFeature("Width");                if (widthFeature != null && featureCtrl.IsWritable("Width"))                {                    widthFeature.SetValue(width);                    mWidth = width;                    // 重新计算行步长                    GetImageSizeAndPayload();                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置宽度失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 设置图像高度(文档2.10.6.2节)        /// </summary>        private void SetImageHeight(int height)        {            try            {                if (height <= 0 || height > mHeightMax)                {                    Log.Error($"高度值{height}超出范围(0-{mHeightMax})");                    return;                }                // 正确:通过IGXFeatureControl调用IsWritable()判断属性是否可写                IGXFeatureControl featureCtrl = _gxDevice.GetRemoteFeatureControl(); // 获取属性控制器                var heightFeature = _remoteFeatureCtrl.GetIntFeature("Height");                if (heightFeature != null && featureCtrl.IsWritable("Height"))                {                    heightFeature.SetValue(height);                    mHeight = height;                    // 重新计算行步长                    GetImageSizeAndPayload();                }            }            catch (CGalaxyException ex)            {                Log.Error($"设置高度失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");            }        }        /// <summary>        /// 帧回调函数(文档2.11.3节,使用IframeData接口)        /// </summary>        private void frameCallbackFunc(object objUserParam, IframeData frameData)        {            IntPtr pConvertedBuffer = IntPtr.Zero;            try            {                // 检查帧状态(文档6.15.1节)                if (frameData.GetStatus() != GX_frame_STATUS_LIST.GX_frame_STATUS_SUCCESS)                {                    Log.Error($"接收无效帧,状态码:{frameData.GetStatus()}");                    return;                }                // 获取帧信息(文档6.15节)                uint width = (uint)frameData.GetWidth();                uint height = (uint)frameData.GetHeight();                GX_PIXEL_FORMAT_ENTRY pixelFormat = frameData.GetPixelFormat();                // 图像格式转换(文档6.18节)                pConvertedBuffer = ConvertImageFormat(frameData, pixelFormat, width, height);                if (pConvertedBuffer == IntPtr.Zero)                {                    Log.Error("图像格式转换失败");                    return;                }                // 转换为VisionPro图像                Image = ConvertToCogImage(pConvertedBuffer, width, height, pixelFormat);                if (Image != null)                {                    ImageGrab?.Invoke(Image);                }                EventWait.Set();            }            catch (CGalaxyException ex)            {                Log.Error($"帧回调失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                EventWait.Set();            }            catch (Exception ex)            {                Log.Error($"帧回调异常:{ex.Message}");                EventWait.Set();            }            finally            {                // 释放转换缓冲区                if (pConvertedBuffer != IntPtr.Zero)                {                    Marshal.FreeHGlobal(pConvertedBuffer);                    pConvertedBuffer = IntPtr.Zero;                }            }        }        /// <summary>        /// 图像格式转换(文档6.18节,IGXImageFormatConvert接口)        /// </summary>        private IntPtr ConvertImageFormat(IframeData frameData, GX_PIXEL_FORMAT_ENTRY srcFormat, uint width, uint height)        {            try            {                // 创建格式转换对象(文档6.1.13节)                IGXImageFormatConvert convertor = IGXFactory.GetInstance().CreateImageFormatConvert();                if (convertor == null)                {                    return IntPtr.Zero;                }                // 设置目标格式(优先转为Mono8或RGB8)                GX_PIXEL_FORMAT_ENTRY dstFormat = IsMonoPixelFormat(srcFormat)                    ? GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8                    : GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8;                convertor.SetDstFormat(dstFormat);                convertor.SetInterpolationType(GX_BAYER_CONVERT_TYPE_LIST.GX_RAW2RGB_NEIGHBOUR);                // 设置有效位(文档6.18.12节)                if (!IsMono8OrRgb8(srcFormat))                {                    convertor.SetValidBits(GetDefaultValidBits(srcFormat));                }                // 计算目标缓冲区大小(文档6.18.8节)                ulong bufferSize = convertor.GetBufferSizeForConversion(width, height, srcFormat);                IntPtr dstBuffer = Marshal.AllocHGlobal((int)bufferSize);                if (dstBuffer == IntPtr.Zero)                {                    return IntPtr.Zero;                }                // 执行转换(文档6.18.11节)                convertor.Convert(frameData.GetBuffer(), width, height, srcFormat, dstBuffer, bufferSize, false);                return dstBuffer;            }            catch (CGalaxyException ex)            {                Log.Error($"格式转换失败:错误码{ex.GetErrorCode()},描述:{ex.Message}");                return IntPtr.Zero;            }        }        /// <summary>        /// 判断是否为Mono像素格式(文档3.6节)        /// </summary>        private bool IsMonoPixelFormat(GX_PIXEL_FORMAT_ENTRY pixelFormat)        {            return pixelFormat.ToString().StartsWith("GX_PIXEL_FORMAT_MONO");        }        /// <summary>        /// 判断是否为Mono8或RGB8格式        /// </summary>        private bool IsMono8OrRgb8(GX_PIXEL_FORMAT_ENTRY pixelFormat)        {            return pixelFormat == GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8                || pixelFormat == GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8;        }        /// <summary>        /// 获取默认有效位(文档3.10节,GX_VALID_BIT_LIST)        /// </summary>        private GX_VALID_BIT_LIST GetDefaultValidBits(GX_PIXEL_FORMAT_ENTRY pixelFormat)        {            GX_VALID_BIT_LIST gX_VALID_BIT_LIST = new GX_VALID_BIT_LIST();            switch (pixelFormat)            {                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_UNDEFINED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8_SIGNED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10:                    gX_VALID_BIT_LIST = GX_VALID_BIT_LIST.GX_BIT_2_9;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12:                    gX_VALID_BIT_LIST = GX_VALID_BIT_LIST.GX_BIT_4_11;                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG14_P:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGBA8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB8_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB10_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB12_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_RGB16_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGRA8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR10:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR12:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR14:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BGR16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_R8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_G8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_B8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_ABC32F:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_ABC32F_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR601_422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YCBCR709_422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV444_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV411_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV422_8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV422_8_UYVY:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_BG12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GB12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_GR12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG10_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_BAYER_RG12_PACKED:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_YUV420_8_PLANAR:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_ARGB8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_ABGR8:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_I16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_S16:                    break;                case GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_COORD3D_C16_I16_S16:                    break;                default:                    break;            }            return gX_VALID_BIT_LIST;        }        /// <summary>        /// 转换为VisionPro ICogImage(文档2.11.5节)        /// </summary>        private ICogImage ConvertToCogImage(IntPtr pBuffer, uint width, uint height, GX_PIXEL_FORMAT_ENTRY pixelFormat)        {            try            {                if (IsMonoPixelFormat(pixelFormat) || pixelFormat == GX_PIXEL_FORMAT_ENTRY.GX_PIXEL_FORMAT_MONO8)                {                    // Mono8图像                    CogImage8Root greyRoot = new CogImage8Root();                    greyRoot.Initialize((int)width, (int)height, pBuffer, (int)width, null);                    CogImage8Grey greyImage = new CogImage8Grey();                    greyImage.SetRoot(greyRoot);                    return greyImage.ScaleImage((int)width, (int)height);                }                else                {                    // RGB8图像                    CogImage8Root rRoot = new CogImage8Root();                    CogImage8Root gRoot = new CogImage8Root();                    CogImage8Root bRoot = new CogImage8Root();                    // 分离RGB通道                    byte[] rgbData = new byte[width * height * 3];                    Marshal.Copy(pBuffer, rgbData, 0, rgbData.Length);                    byte[] rData = new byte[width * height];                    byte[] gData = new byte[width * height];                    byte[] bData = new byte[width * height];                    for (int i = 0; i < height; i++)                    {                        for (int j = 0; j < width; j++)                        {                            int index = (int)(i * width * 3 + j * 3);                            rData[i * width + j] = rgbData[index];                            gData[i * width + j] = rgbData[index + 1];                            bData[i * width + j] = rgbData[index + 2];                        }                    }                    // 初始化RGB通道                    rRoot.Initialize((int)width, (int)height, Marshal.UnsafeAddrOfPinnedArrayElement(rData, 0), (int)width, null);                    gRoot.Initialize((int)width, (int)height, Marshal.UnsafeAddrOfPinnedArrayElement(gData, 0), (int)width, null);                    bRoot.Initialize((int)width, (int)height, Marshal.UnsafeAddrOfPinnedArrayElement(bData, 0), (int)width, null);                    CogImage24PlanarColor colorImage = new CogImage24PlanarColor();                    colorImage.SetRoots(rRoot, gRoot, bRoot);                    return colorImage.ScaleImage((int)width, (int)height);                }            }            catch (Exception ex)            {                Log.Error($"转换VisionPro图像失败:{ex.Message}");                return null;            }        }        #endregion        #region IDisposable实现(文档2.3节,SDK反初始化)        public void Dispose()        {            Dispose(true);            GC.SuppressFinalize(this);        }        protected virtual void Dispose(bool disposing)        {            if (_disposed)            {                return;            }            // 释放托管资源            if (disposing)            {                EventWait?.Close();                EventWait = null;            }            // 释放非托管资源            DisConnectDev();            // 反初始化SDK(文档2.3节)            IGXFactory.GetInstance().Uninit();            _disposed = true;        }        #endregion    }}

二、相机工厂生成相机

using Common.Camera;namespace Common.Factorys{    public static class CameraFactory    {        public static Camerasbase CreateCamera(CameraType type)        {            Camerasbase camerasbase = null;            switch (type)            {                case CameraType.Basler:                    camerasbase = new CamerasHikvision();                    break;                case CameraType.Hikvision:                    camerasbase = new CamerasHikvision();                    break;                case CameraType.Dahua:                    camerasbase = new CamerasHikvision();                    break;                case CameraType.Daheng:                    camerasbase = new CamerasHikvision();                    break;                default:                    camerasbase = new CamerasHikvision();                    break;            }            return camerasbase;        }    }    public enum CameraType    {        Basler,        Hikvision,        Dahua,        Daheng    }}

三、程序调用

大恒相机(Galaxy )SDK C# 取图完整代码,可直接使用nerror="javascript:errorimg.call(this);">

四、界面展示

大恒相机(Galaxy )SDK C# 取图完整代码,可直接使用nerror="javascript:errorimg.call(this);">

代码说明

架构一致性:完全沿用代码架构(抽象基类Camerasbase、相机信息类CamerasInfo、触发模式枚举等),降低迁移成本。

核心功能完整:实现了大恒相机的搜索、连接、断开、抓图、参数设置 / 获取、配置加载 / 保存等全部核心功能。

资源优化:

实现IDisposable接口,确保托管 / 非托管资源(相机设备、流对象、事件句柄)安全释放。

使用try/finally确保非托管内存(Marshal.AllocHGlobal)不泄漏。

自动释放帧缓存(m_gxStream.ReleaseBuffer),避免 SDK 资源占用。

逻辑严谨:

替换魔法值为常量,提高代码可读性。

增加空值判断和参数校验,避免空引用异常。

正确计算行步长(宽度 × 像素字节数),解决图像畸变问题。

兼容性强:支持大恒千兆网(GigE)和USB3.0相机,兼容 VisionPro 图像格式转换。

错误处理:统一使用Log类输出日志支持非 UI 场景运行。


顶一下()     踩一下()

热门推荐

发表评论
0评