HIKCamera.cs 13.5 KB
//引用MvCameraControl.Net.dll
using System;
using MvCamCtrl.NET;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace CodeLibrary
{
    /// <summary>
    /// 海康相机
    /// </summary>
    public class HIKCamera
    {
        public static HIKCamera Instance = new HIKCamera();
        /// <summary>
        /// 当前相机
        /// </summary>
        private MyCamera cameraCurr;
        /// <summary>
        /// 所有相机列表
        /// </summary>
        private MyCamera.MV_CC_DEVICE_INFO_LIST cameraAll;
        /// <summary>
        /// 所有相机的名称
        /// </summary>
        private List<string> cameraName = new List<string>();

        /// <summary>
        /// 海康相机
        /// </summary>
        private HIKCamera()
        {
            cameraAll = new MyCamera.MV_CC_DEVICE_INFO_LIST();
            Load();
        }

        /// <summary>
        /// 错误信息
        /// </summary>
        public string ErrInfo { set; get; }

        /// <summary>
        /// 相机总数
        /// </summary>
        public int Count
        {
            get { return (int)cameraAll.nDeviceNum; }
        }

        /// <summary>
        /// 相机名称,ModelName,SerialNumber
        /// </summary>
        public string[] CameraName
        {
            get
            {
                if (cameraName == null)
                {
                    cameraName = new List<string>();
                }
                return cameraName.ToArray(); }
        }

        /// <summary>
        /// 当前相机是否打开
        /// </summary>
        public bool IsOpen
        {
            get
            {
                if (cameraCurr == null)
                    return false;
                else
                    return true;
            }
        }

        /// <summary>
        /// 相机图像宽度
        /// </summary>
        public int Width { set; get; }

        /// <summary>
        /// 相机图像高度
        /// </summary>
        public int Height { set; get; }

        /// <summary>
        /// 相机32位缓存
        /// </summary>
        public byte[] Buffer { get; private set; }

        /// <summary>
        /// 相机32位图像
        /// </summary>
        public Bitmap Image { get; private set; }

        /// <summary>
        /// 加载相机
        /// </summary>
        public void Load()
        {
            try
            {
                int rtn = MyCamera.MV_CC_EnumDevices_NET(MyCamera.MV_GIGE_DEVICE | MyCamera.MV_USB_DEVICE, ref cameraAll);
                if (rtn != MyCamera.MV_OK) return;
                cameraName.Clear();
                string s = "";

                for (int i = 0; i < cameraAll.nDeviceNum; i++)
                {
                    MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(cameraAll.pDeviceInfo[i], typeof(MyCamera.MV_CC_DEVICE_INFO));
                    if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                    {
                        IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stGigEInfo, 0);
                        MyCamera.MV_GIGE_DEVICE_INFO gigeInfo = (MyCamera.MV_GIGE_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_GIGE_DEVICE_INFO));
                        s = "GigE:" + gigeInfo.chModelName + " (" + gigeInfo.chSerialNumber + ")";
                    }
                    else if (device.nTLayerType == MyCamera.MV_USB_DEVICE)
                    {
                        IntPtr buffer = Marshal.UnsafeAddrOfPinnedArrayElement(device.SpecialInfo.stUsb3VInfo, 0);
                        MyCamera.MV_USB3_DEVICE_INFO usbInfo = (MyCamera.MV_USB3_DEVICE_INFO)Marshal.PtrToStructure(buffer, typeof(MyCamera.MV_USB3_DEVICE_INFO));
                        s = "USB:" + usbInfo.chModelName + " (" + usbInfo.chSerialNumber + ")";
                    }
                    cameraName.Add(s);
                }
            }
            catch (Exception ex)
            {
                HDLogUtil.error("HIK Load Error:" + ex.StackTrace);
            }
        }

        /// <summary>
        /// 打开指定相机
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public bool Open(string name)
        {
            int n = cameraName.FindIndex(s => s == name);
            if (n == -1)
                return false;
            else
                return Open(n);
        }

        /// <summary>
        /// 打开指定相机
        /// </summary>
        /// <param name="idx">索引</param>
        /// <returns></returns>
        public bool Open(int idx)
        {
            if (idx < 0 || idx >= Count) return false;
            if (cameraCurr != null) Close();

            try
            {
                MyCamera.MV_CC_DEVICE_INFO device = (MyCamera.MV_CC_DEVICE_INFO)Marshal.PtrToStructure(cameraAll.pDeviceInfo[idx], typeof(MyCamera.MV_CC_DEVICE_INFO));
                cameraCurr = new MyCamera();
                if (cameraCurr == null) return false;
             
                int nRet = cameraCurr.MV_CC_CreateDevice_NET(ref device);
                if (nRet != MyCamera.MV_OK) return false;
                nRet = cameraCurr.MV_CC_OpenDevice_NET();
                if (nRet != MyCamera.MV_OK)
                {
                    cameraCurr.MV_CC_DestroyDevice_NET();
                    return false;
                }

                if (device.nTLayerType == MyCamera.MV_GIGE_DEVICE)
                {
                    int nPacketSize = cameraCurr.MV_CC_GetOptimalPacketSize_NET();
                    if (nPacketSize > 0) nRet = cameraCurr.MV_CC_SetIntValue_NET("GevSCPSPacketSize", (uint)nPacketSize);
                }
                cameraCurr.MV_CC_SetEnumValue_NET("AcquisitionMode", 2);  //工作在连续模式
                cameraCurr.MV_CC_SetEnumValue_NET("TriggerMode", 0);  //连续模式
                MyCamera.MVCC_INTVALUE pstValue = new MyCamera.MVCC_INTVALUE();
                nRet = cameraCurr.MV_CC_GetWidth_NET(ref pstValue);
                Width = (int)pstValue.nCurValue;
                nRet = cameraCurr.MV_CC_GetHeight_NET(ref pstValue);
                Height = (int)pstValue.nCurValue;

                return true;
            }
            catch (Exception ex)
            {
                ErrInfo = ex.Message;
                return false;
            }
        }

        /// <summary>
        /// 关闭当前相机
        /// </summary>
        public void Close()
        {
            if (cameraCurr != null)
            {
                cameraCurr.MV_CC_CloseDevice_NET();
                cameraCurr.MV_CC_DestroyDevice_NET();
                cameraCurr = null;
            }
        }

        /// <summary>
        /// 停止抓取数据
        /// </summary>
        public void Stop()
        {
            if (cameraCurr == null) return;
            int rtn = cameraCurr.MV_CC_StopGrabbing_NET();
            if (rtn != MyCamera.MV_OK) return;
        }

        /// <summary>
        /// 抓取一张图像
        /// </summary>
        public void GrabOne()
        {
            int rtn = cameraCurr.MV_CC_StartGrabbing_NET();
            if (rtn != MyCamera.MV_OK) return;

            MyCamera.MVCC_INTVALUE stParam = new MyCamera.MVCC_INTVALUE();
            rtn = cameraCurr.MV_CC_GetIntValue_NET("PayloadSize", ref stParam);
            if (rtn != MyCamera.MV_OK) return;

            uint dataSize = stParam.nCurValue;
            byte[] dataArr = new byte[dataSize];
            uint buffSize = dataSize * 3 + 2048;
            byte[] buffArr = new byte[buffSize];
            IntPtr pData = Marshal.UnsafeAddrOfPinnedArrayElement(dataArr, 0);
            MyCamera.MV_FRAME_OUT_INFO_EX stFrameInfo = new MyCamera.MV_FRAME_OUT_INFO_EX();
            rtn = cameraCurr.MV_CC_GetOneFrameTimeout_NET(pData, dataSize, ref stFrameInfo, 100000);
            if (rtn != MyCamera.MV_OK) return;

            MyCamera.MvGvspPixelType enDstPixelType = stFrameInfo.enPixelType;
            switch (stFrameInfo.enPixelType)
            {
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono12_Packed:
                    enDstPixelType = stFrameInfo.enPixelType; break;
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG8:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG10_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGR12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerRG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerGB12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_BayerBG12_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YUV422_YUYV_Packed:
                case MyCamera.MvGvspPixelType.PixelType_Gvsp_YCBCR411_8_CBYYCRYY:
                    enDstPixelType = MyCamera.MvGvspPixelType.PixelType_Gvsp_RGB8_Packed; break;
            }
            IntPtr pImage = Marshal.UnsafeAddrOfPinnedArrayElement(buffArr, 0);
            MyCamera.MV_PIXEL_CONVERT_PARAM stConverPixelParam = new MyCamera.MV_PIXEL_CONVERT_PARAM();
            stConverPixelParam.nWidth = stFrameInfo.nWidth;
            stConverPixelParam.nHeight = stFrameInfo.nHeight;
            stConverPixelParam.pSrcData = pData;
            stConverPixelParam.nSrcDataLen = stFrameInfo.nFrameLen;
            stConverPixelParam.enSrcPixelType = stFrameInfo.enPixelType;
            stConverPixelParam.enDstPixelType = enDstPixelType;
            stConverPixelParam.pDstBuffer = pImage;
            stConverPixelParam.nDstBufferSize = buffSize;
            rtn = cameraCurr.MV_CC_ConvertPixelType_NET(ref stConverPixelParam);
            if (rtn != MyCamera.MV_OK) return;

            if (enDstPixelType == MyCamera.MvGvspPixelType.PixelType_Gvsp_Mono8)
            {
                Image = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 1, PixelFormat.Format8bppIndexed, pImage);
                ColorPalette cp = Image.Palette;
                for (int i = 0; i < 256; i++)
                    cp.Entries[i] = Color.FromArgb(i, i, i);
                Image.Palette = cp;

                int picSize = Image.Width * Image.Height;
                Buffer = new byte[picSize];
                Array.Copy(buffArr, Buffer, picSize);


                //Rectangle rect = new Rectangle(0, 0, Image.Width, Image.Height);
                //BitmapData bmpData = Image.LockBits(rect, ImageLockMode.ReadWrite, Image.PixelFormat);
                //IntPtr iPtr = bmpData.Scan0;
                //int picSize = Image.Width * Image.Height;
                //Buffer = new byte[picSize];
                //Marshal.Copy(iPtr, Buffer, 0, picSize);
                //Image.UnlockBits(bmpData);
            }
            else
            {
                for (int i = 0; i < stFrameInfo.nHeight; i++)
                {
                    for (int j = 0; j < stFrameInfo.nWidth; j++)
                    {
                        byte chRed = buffArr[i * stFrameInfo.nWidth * 3 + j * 3];
                        buffArr[i * stFrameInfo.nWidth * 3 + j * 3] = buffArr[i * stFrameInfo.nWidth * 3 + j * 3 + 2];
                        buffArr[i * stFrameInfo.nWidth * 3 + j * 3 + 2] = chRed;
                    }
                }
                Image = new Bitmap(stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.nWidth * 3, PixelFormat.Format24bppRgb, pImage);
                int picSize = Image.Width * Image.Height * 3;
                Buffer = new byte[picSize];
                Array.Copy(buffArr, Buffer, picSize);
            }

            rtn = cameraCurr.MV_CC_StopGrabbing_NET();
            if (rtn != MyCamera.MV_OK) return;
        }

        /// <summary>
        /// 抓取连续图像,触发GrabImage事件
        /// </summary>
        /// <param name="hWnd"></param>
        public void GrabContinuous(IntPtr hWnd)
        {
            int rtn = cameraCurr.MV_CC_StartGrabbing_NET();
            if (rtn != MyCamera.MV_OK) return;
            rtn = cameraCurr.MV_CC_Display_NET(hWnd);
            if (rtn != MyCamera.MV_OK) return;
        }

    }
}