zoukankan      html  css  js  c++  java
  • AviCap

    代码
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;

    //namespace AviCap
    //{
    public class AviCap
    {
        
    #region 外部方法
        [DllImport(
    "avicap32.dll")]
        
    public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);

        [DllImport(
    "avicap32.dll")]
        
    public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);

        [DllImport(
    "User32.dll")]
        
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);

        [DllImport(
    "User32.dll")]
        
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);

        
    public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);

        [DllImport(
    "User32.dll")]
        
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);

        [DllImport(
    "User32.dll")]
        
    public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);

        
    /// <summary>
        
    /// 该函数改变一个子窗口,弹出式窗口式顶层窗口的尺寸,位置和Z序。子窗口,弹出式窗口,及顶层窗口根据它们在屏幕上出现的顺序排序、顶层窗口设置的级别最高,并且被设置为Z序的第一个窗口。
        
    /// </summary>
        [DllImport("User32.dll")]
        
    public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);

        [DllImport(
    "avicap32.dll")]
        
    public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
        
    #endregion

        
    #region 消息常量(向窗口发送消息的指令)
        
    //消息常量 --------------------------------------------  
        public const int WM_START = 0x400;    //此并非摄像头消息0x400表示的就是1024  
        public const int WS_CHILD = 0x40000000;
        
    public const int WS_VISIBLE = 0x10000000;
        
    public const int SWP_NOMOVE = 0x2;
        
    public const int SWP_NOZORDER = 0x4;
        
    public const int WM_CAP_GET_CAPSTREAMPTR = WM_START + 1;
        
    public const int WM_CAP_SET_CALLBACK_ERROR = WM_START + 2;//设置收回错误
        public const int WM_CAP_SET_CALLBACK_STATUS = WM_START + 3;//设置收回状态
        public const int WM_CAP_SET_CALLBACK_YIELD = WM_START + 4;//设置收回出产
        public const int WM_CAP_SET_CALLBACK_FRAME = WM_START + 5;//设置收回结构
        public const int WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_START + 6;//设置收回视频流
        public const int WM_CAP_SET_CALLBACK_WAVESTREAM = WM_START + 7;//设置收回视频波流
        public const int WM_CAP_GET_USER_DATA = WM_START + 8;//获得使用者数据
        public const int WM_CAP_SET_USER_DATA = WM_START + 9;//设置使用者数据
        public const int WM_CAP_DRIVER_CONNECT = WM_START + 10;//驱动程序连接
        public const int WM_CAP_DRIVER_DISCONNECT = WM_START + 11;//断开启动程序连接
        public const int WM_CAP_DRIVER_GET_NAME = WM_START + 12;//获得驱动程序名字
        public const int WM_CAP_DRIVER_GET_VERSION = WM_START + 13;//获得驱动程序版本
        public const int WM_CAP_DRIVER_GET_CAPS = WM_START + 14;//获得驱动程序帽子
        public const int WM_CAP_FILE_SET_CAPTURE_FILE = WM_START + 20;//设置捕获文件
        public const int WM_CAP_FILE_GET_CAPTURE_FILE = WM_START + 21;//获得捕获文件
        public const int WM_CAP_FILE_ALLOCATE = WM_START + 22;//分派文件
        public const int WM_CAP_FILE_SAVEAS = WM_START + 23;//另存文件为
        public const int WM_CAP_FILE_SET_INFOCHUNK = WM_START + 24;//设置开始文件
        public const int WM_CAP_FILE_SAVEDIB = WM_START + 25;//保存文件
        public const int WM_CAP_EDIT_COPY = WM_START + 30;//编辑复制
        public const int WM_CAP_SET_AUDIOFORMAT = WM_START + 35;//设置音频格式
        public const int WM_CAP_GET_AUDIOFORMAT = WM_START + 36;//捕获音频格式
        public const int WM_CAP_DLG_VIDEOFORMAT = WM_START + 41;//1065 打开视频格式设置对话框
        public const int WM_CAP_DLG_VIDEOSOURCE = WM_START + 42;//1066 打开属性设置对话框,设置对比度亮度等
        public const int WM_CAP_DLG_VIDEODISPLAY = WM_START + 43;//1067 打开视频显示
        public const int WM_CAP_GET_VIDEOFORMAT = WM_START + 44;//1068 获得视频格式
        public const int WM_CAP_SET_VIDEOFORMAT = WM_START + 45;//1069 设置视频格式
        public const int WM_CAP_DLG_VIDEOCOMPRESSION = WM_START + 46;//1070 打开压缩设置对话框
        public const int WM_CAP_SET_PREVIEW = WM_START + 50;//设置预览
        public const int WM_CAP_SET_OVERLAY = WM_START + 51;//设置覆盖
        public const int WM_CAP_SET_PREVIEWRATE = WM_START + 52;//设置预览比例
        public const int WM_CAP_SET_SCALE = WM_START + 53;//设置刻度
        public const int WM_CAP_GET_STATUS = WM_START + 54;//获得状态
        public const int WM_CAP_SET_SCROLL = WM_START + 55;//设置卷
        public const int WM_CAP_GRAB_FRAME = WM_START + 60;//逮捕结构
        public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_START + 61;//停止逮捕结构
        public const int WM_CAP_SEQUENCE = WM_START + 62;//次序
        public const int WM_CAP_SEQUENCE_NOFILE = WM_START + 63;//使用WM_CAP_SEUENCE_NOFILE消息(capCaptureSequenceNoFile宏),可以不向磁盘文件写入数据。该消息仅在配合回调函数时有用,它允许你的应用程序直接使用音视频数据。
        public const int WM_CAP_SET_SEQUENCE_SETUP = WM_START + 64;//设置安装次序
        public const int WM_CAP_GET_SEQUENCE_SETUP = WM_START + 65;//获得安装次序
        public const int WM_CAP_SET_MCI_DEVICE = WM_START + 66;//设置媒体控制接口
        public const int WM_CAP_GET_MCI_DEVICE = WM_START + 67;//获得媒体控制接口 
        public const int WM_CAP_STOP = WM_START + 68;//停止
        public const int WM_CAP_ABORT = WM_START + 69;//异常中断
        public const int WM_CAP_SINGLE_FRAME_OPEN = WM_START + 70;//打开单一的结构
        public const int WM_CAP_SINGLE_FRAME_CLOSE = WM_START + 71;//关闭单一的结构
        public const int WM_CAP_SINGLE_FRAME = WM_START + 72;//单一的结构
        public const int WM_CAP_PAL_OPEN = WM_START + 80;//打开视频
        public const int WM_CAP_PAL_SAVE = WM_START + 81;//保存视频
        public const int WM_CAP_PAL_PASTE = WM_START + 82;//粘贴视频
        public const int WM_CAP_PAL_AUTOCREATE = WM_START + 83//自动创造
        public const int WM_CAP_PAL_MANUALCREATE = WM_START + 84;//手动创造
        public const int WM_CAP_SET_CALLBACK_CAPCONTROL = WM_START + 85;// 设置收回的错误


        
    //其它
        public const int WM_CAP_SAVEDIB = WM_CAP_START + 25;

        
    public const int WM_USER = 0x400;//1024

        
    public const int WM_CAP_START = WM_USER;

        
    public const int WM_CAP_UNICODE_START = WM_USER + 100//开始

        
    public const int WM_CAP_GRAB_FRame = (WM_CAP_START + 60); //逮捕结构
        public const int WM_CAP_GRAB_FRame_NOSTOP = (WM_CAP_START + 61); //停止逮捕结构

        
    public const int WM_CAP_SINGLE_FRame_OPEN = (WM_CAP_START + 70); //打开单一的结构
        public const int WM_CAP_SINGLE_FRame_CLOSE = (WM_CAP_START + 71); //关闭单一的结构
        public const int WM_CAP_SINGLE_FRame = (WM_CAP_START + 72); //单一的结构

        
    // Following added post VFW 1.1
        public const int WM_CAP_END = WM_CAP_SET_CALLBACK_CAPCONTROL;

        
    #endregion

        
    #region 结构体
        [StructLayout(LayoutKind.Sequential)]
        
    public struct VIDEOHDR
        {
            [MarshalAs(UnmanagedType.I4)]
            
    public int lpData;
            [MarshalAs(UnmanagedType.I4)]
            
    public int dwBufferLength;
            [MarshalAs(UnmanagedType.I4)]
            
    public int dwBytesUsed;
            [MarshalAs(UnmanagedType.I4)]
            
    public int dwTimeCaptured;
            [MarshalAs(UnmanagedType.I4)]
            
    public int dwUser;
            [MarshalAs(UnmanagedType.I4)]
            
    public int dwFlags;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst 
    = 4)]
            
    public int[] dwReserved;
        }

        [StructLayout(LayoutKind.Sequential)]
        
    public struct BITMAPINFOHEADER
        {
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biSize;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biWidth;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biHeight;
            [MarshalAs(UnmanagedType.I2)]
            
    public short biPlanes;
            [MarshalAs(UnmanagedType.I2)]
            
    public short biBitCount;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biCompression;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biSizeImage;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biXPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biYPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biClrUsed;
            [MarshalAs(UnmanagedType.I4)]
            
    public Int32 biClrImportant;
        }


        
    #region BITMAPINFO结构
        
    //BITMAPINFO结构具有如下形式:
        
    //typedef struct tagBITMAPINFO
        
    //{
        
    //   BITMAPINFOHEADER  bmiHeader;
        
    //   RGBQUAD           bmiColors[1];
        
    //}  BITMAPINFO;

        
    //BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。

        
    //成员:
        
    //bmiHeader    指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
        
    //bmiColors    指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。

        
    //注释:
        
    //设备无关位图由两个部分组成:
        
    //(1)    一个BITMAPINFO结构,描述了位图的度量和颜色信息;
        
    //(2)    一个字节数组,定义了位图的像素。数组中的字节被组合在一起,但是每个扫描行必须用零填补,在一个LONG边界结束。如果高度为正的,位图的起始位置在左下角。如果高度为负,起始位置在左上角。
        
    //(3)    BITMAPINFOHEADER结构中的biBitCount成员决定了定义像素的位数以及位图中的最大颜色数。这个成员可以是下列值之一:
        
    //·    位图是单色的,bmiColors成员包含两个入口。位图数组中的每一位代表一个像素。如果该位被清除,则用bmiColors表中的第一种颜色显示该像素。如果该位被置位,则用表中的第二种颜色显示该像素。
        
    //·    位图最多有16种颜色,bmiColors成员中包含了最多可达16个入口。位图中的每个像素用一个4位的值来表示,该值用作颜色表的索引。例如,如果位图中的第一个字节是0x1F,这个字节代表两个像素。第一个像素包含了颜色表中第二种颜色,第二个像素包含了颜色表中第十六种颜色。
        
    //·    位图最多有256种颜色,bmiColors成员包含了多达256个入口。在这种情况下,数组中的每个字节代表一个像素。
        
    //·    位图最多有216种颜色。BITMAPINFOHEADER的biCompression成员必须是BI_BITFIELDS。bmiColors成员包含了3个DWORD型颜色掩码,分别代表了每个像素中的红,绿和蓝色成分。DWORD型掩码中的位必须是连续的,不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个WORD值代表一个像素。
        
    //·    位图最多具有224种颜色,bmiColors成员为NULL。位图数组中的每个三字节组合分别代表像素中蓝,绿红的深度。
        
    //·    位图中最多具有232种颜色。BITMAPINFOHEADER中的biCompression成员必须是BI_BITFIELDS。bmiColors成员中包含了三个DWORD颜色掩码,分别指定了像素的红,绿和蓝成分。DWORD掩码中的位必须是连续的,并且不能与其它掩码重叠。并非像素中的所有位都必须被使用。数组中的每个DWORD值代表一个像素。
        
    //BITMAPINFOHEADER结构中的biClrUsed成员指定了颜色表中实际使用的索引的数目。如果biClrUsed成员被设为0,位图将使用biBitCount成员中指定的最大颜色数。
        
    //bmiColors表中的颜色应当按照其重要性的顺序出现。另一种情况是,对于使用DIB函数,bmiColors成员可以是一个16位无符号整数的数组,指定了当前实现的逻辑调色板中的索引,而不是确切的RGB值。在这种情况下,使用位图的应用程序必须调用Windows的DIB函数(CreateDIBitmap,CreateDIBPatternBrush和CreateDIBSection),iUsage参数应被设为DIB_PAL_COLORS。
        
    //如果位图是一个压缩位图(这意味着,这种位图的数组直接跟在一个指针所引用的BITMAPINFO头的后面),在使用DIB_PAL_COLORS模式的时候,biClrUsed成员必须被设为偶数,以便使DIB位图数组从DWORD边界开始。
        
    //注意:
        
    //如果位图被保存在文件中,或者要被传送到另一个应用程序,bmiColors成员不能包含调色板索引。除非应用程序独占地使用和控制位图,位图的颜色表中应当包含准确的RGB值。
        #endregion
        
    /// <summary>
        
    /// BITMAPINFO结构定义了Windows设备无关位图(DIB)的度量和颜色信息。
        
    /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        
    public struct BITMAPINFO
        {
            
    /// <summary>
            
    /// 指定了一个BITMAPINFOHEADER结构,包含了有关设备相关位图的度量和颜色格式的信息。
            
    /// </summary>
            [MarshalAs(UnmanagedType.Struct, SizeConst = 40)]
            
    public BITMAPINFOHEADER bmiHeader;

            
    /// <summary>
            
    /// 指定了一个RGBQUAD或DWORD数据类型的数组,定义了位图中的颜色。
            
    /// </summary>
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
            
    public Int32[] bmiColors;
        }

        
    #endregion

        
    #region 属性
        
    private IntPtr lwndC; // 保存无符号句柄
        private IntPtr mControlPtr; //保存管理指示器 用于显示视频内容的控件地址指针 
        private int mWidth;
        
    private int mHeight;

        
    //委托 祯 回调事件定义
        public delegate void RecievedFrameEventHandler(byte[] data);
        
    public event RecievedFrameEventHandler RecievedFrame;

        
    private FrameEventHandler mFrameEventHandler; // Delegate instance for the frame callback - must keep alive! gc should NOT collect it

        
    #endregion

        
    /// <summary>
        
    /// 构造方法
        
    /// </summary>
        
    /// <param name="handle">显示视频控件的句柄</param>
        
    /// <param name="width">视频宽度</param>
        
    /// <param name="height">视频高度</param>
        public AviCap(IntPtr handle, int width, int height)
        {
            mControlPtr 
    = handle;
            mWidth 
    = width;
            mHeight 
    = height;
        }

        
    #region 静态方法
        
    public static object GetStructure(IntPtr ptr, ValueType structure)
        {
            
    return Marshal.PtrToStructure(ptr, structure.GetType());
        }

        
    public static object GetStructure(int ptr, ValueType structure)
        {
            
    return GetStructure(new IntPtr(ptr), structure);
        }

        
    public static void Copy(IntPtr ptr, byte[] data)
        {
            Marshal.Copy(ptr, data, 
    0, data.Length);
        }

        
    public static void Copy(int ptr, byte[] data)
        {
            Copy(
    new IntPtr(ptr), data);
        }

        
    public static int SizeOf(object structure)
        {
            
    return Marshal.SizeOf(structure);
        }

        
    #endregion

        
    //开启摄像头方法
        public void StartWebCam()
        {
            
    byte[] lpszName = new byte[100];//名字
            byte[] lpszVer = new byte[100];//版本号

            AviCap.capGetDriverDescriptionA(
    0, lpszName, 100, lpszVer, 100);
            
    this.lwndC = AviCap.capCreateCaptureWindowA(lpszName, WS_VISIBLE + WS_CHILD, 00, mWidth, mHeight, mControlPtr, 0);

            
    if (this.DriverConnect(0))
            {
                
    this.PreviewRate(66);
                
    this.Preview(true);

                BITMAPINFO bitmapinfo 
    = new BITMAPINFO();
                bitmapinfo.bmiHeader.biSize 
    = AviCap.SizeOf(bitmapinfo.bmiHeader);
                
    //bitmapinfo.bmiHeader.biWidth = 352;
                
    //bitmapinfo.bmiHeader.biHeight = 288; 
                bitmapinfo.bmiHeader.biWidth = mWidth;
                bitmapinfo.bmiHeader.biHeight 
    = mHeight;
                bitmapinfo.bmiHeader.biPlanes 
    = 1;
                bitmapinfo.bmiHeader.biBitCount 
    = 24;
                
    //this.SetVideoFormat(ref bitmapinfo, AviCap.SizeOf(bitmapinfo));
                
    //this.mFrameEventHandler = new AviCap.FrameEventHandler(FrameCallBack);
                this.SetCallbackOnFrame(this.mFrameEventHandler);
                AviCap.SetWindowPos(
    this.lwndC, 000, mWidth, mHeight, 6);
            }

            
    //byte[] lpszName = new byte[100];
            
    //byte[] lpszVer = new byte[100];
            
    //VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
            
    //this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);
            
    //if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))
            
    //{
            
    //    VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0);
            
    //    VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0);
            
    //}
        }

        
    //关闭摄像头方法
        public void CloseWebcam()
        {
            
    this.DriverDisconnect();
        }

        
    /// <summary>
        
    /// 拍照
        
    /// </summary>
        
    /// <param name="path">BMP路由</param>
        public void GrabImage(string path)
        {
            IntPtr hBmp 
    = Marshal.StringToHGlobalAnsi(path);
            SendMessage(
    this.lwndC, WM_CAP_SAVEDIB, 0, hBmp.ToInt32());
        }


        
    public bool DriverConnect(short nCameraID)
        {
            
    return SendMessage(this.lwndC, WM_CAP_DRIVER_CONNECT, nCameraID, 0);
        }

        
    /// <summary>
        
    /// 驱动断开
        
    /// </summary>
        
    /// <param name="lwnd"></param>
        
    /// <returns></returns>
        public bool DriverDisconnect()
        {
            
    return SendMessage(this.lwndC, WM_CAP_DRIVER_DISCONNECT, 00);
        }

        
    /// <summary>
        
    /// 预览
        
    /// </summary>
        
    /// <param name="f"></param>
        
    /// <returns></returns>
        public bool Preview(bool f)
        {
            
    return SendMessage(this.lwndC, WM_CAP_SET_PREVIEW, f, 0);
        }

        
    /// <summary>
        
    /// 设置预览比例
        
    /// </summary>
        
    /// <param name="wMS"></param>
        
    /// <returns></returns>
        public bool PreviewRate(short wMS)
        {
            
    return SendMessage(this.lwndC, WM_CAP_SET_PREVIEWRATE, wMS, 0);
        }

        
    /// <summary>
        
    /// 设置回调事件
        
    /// </summary>
        private bool SetCallbackOnFrame(FrameEventHandler lpProc)
        {
            
    return SendMessage(this.lwndC, WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);
        }

        
    /// <summary>
        
    /// 设置视频格式
        
    /// </summary>
        
    /// <param name="hCapWnd"></param>
        
    /// <param name="BmpFormat"></param>
        
    /// <param name="CapFormatSize"></param>
        
    /// <returns></returns>
        public bool SetVideoFormat(ref BITMAPINFO BmpFormat, int CapFormatSize)
        {
            
    return SendMessage(this.lwndC, WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
        }

        
    private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
        {
            VIDEOHDR videoHeader 
    = new VIDEOHDR();
            
    byte[] VideoData;
            videoHeader 
    = (VIDEOHDR)GetStructure(lpVHdr, videoHeader);
            VideoData 
    = new byte[videoHeader.dwBytesUsed];
            Copy(videoHeader.lpData, VideoData);
            
    if (this.RecievedFrame != null)
                
    this.RecievedFrame(VideoData);
        }

    }
    //}
  • 相关阅读:
    day 13 闭包函数,装饰器,迭代器
    day12 可变长参数、函数对象、函数的嵌套、名称空间和作用域
    day11 文件的高级应用、文件修改的两种方式、函数的定义、函数的三种定义方式、函数的调用、函数的返回值、函数的参数
    数字类型内置方法
    基本语法之for循环
    基本语法之while循环
    python基本语法(3)
    python基本语法(2)
    python基本语法(1)
    编程及计算机组成
  • 原文地址:https://www.cnblogs.com/jgjgjg23/p/1778530.html
Copyright © 2011-2022 走看看