WebCamera.cs 5.04 KB
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace WebCam
{
	public class WebCameraEventArgs : EventArgs
	{
		private System.Drawing.Bitmap bitMap;
		private byte[] data;
		public WebCameraEventArgs(byte[] videoData, System.Drawing.Bitmap bmp)
		{
			data = videoData;
			bitMap = bmp;
		}
		public byte[] Data
		{
			get
			{
				return data;
			}
		}
		public System.Drawing.Bitmap Bitmap
		{
			get
			{
				return bitMap;
			}
		}
	}
	
	public class WebCamera
	{


		public WebCamera(IntPtr handle, int width, int height)

		{
			mControlPtr = handle;
			mWidth = width;
			mHeight = height;
		}

		// delegate for frame callback

		public delegate void RecievedFrameEventHandler(object sender,WebCameraEventArgs e);
		public event RecievedFrameEventHandler RecievedFrame;
		private IntPtr lwndC; // Holds the unmanaged handle of the control
		private IntPtr mControlPtr; // Holds the managed pointer of the control
		private int mWidth;
		private int mHeight;
		private API32.FrameEventHandler mFrameEventHandler; // Delegate instance for the frame callback - must keep alive! gc should NOT collect it
		// Close the web camera

		public void CloseWebcam()
		{
			this.capDriverDisconnect(this.lwndC);
		}

		// start the web camera
		public bool StartWebCam()
		{

			byte[] lpszName = new byte[100];
			byte[] lpszVer = new byte[100];
			API32.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
			this.lwndC = API32.capCreateCaptureWindowA(lpszName, API32.WS_VISIBLE + API32.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0);
	
			if (this.capDriverConnect(this.lwndC, 0))
			{

				this.capPreviewRate(this.lwndC, 100);
				//this.capPreview(this.lwndC, false); // resurssi, pivitetnk kuvaa jatkuvasti
				API32.BITMAPINFO bitmapinfo = new API32.BITMAPINFO();
				bitmapinfo.bmiHeader.biSize = API32.SizeOf(bitmapinfo.bmiHeader);

				bitmapinfo.bmiHeader.biWidth = mWidth;
				bitmapinfo.bmiHeader.biHeight = mHeight;

				bitmapinfo.bmiHeader.biPlanes = 1;
				bitmapinfo.bmiHeader.biBitCount = 24;
				this.capSetVideoFormat(this.lwndC, ref bitmapinfo, API32.SizeOf(bitmapinfo));
				this.mFrameEventHandler = new API32.FrameEventHandler(FrameCallBack);
				this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler);
				API32.SetWindowPos(this.lwndC, 0, 0, 0, mWidth, mHeight, 6);
				return true;

			}
			return false;
		}

		// private functions

		private bool capDriverConnect(IntPtr lwnd, short i)

		{
			return API32.SendMessage(lwnd, API32.WM_CAP_DRIVER_CONNECT, i, 0);
		}

		private bool capDriverDisconnect(IntPtr lwnd)
		{
			return API32.SendMessage(lwnd, API32.WM_CAP_DRIVER_DISCONNECT, 0, 0);
		}

		private bool capPreview(IntPtr lwnd, bool f)
		{
			return API32.SendMessage(lwnd, API32.WM_CAP_SET_PREVIEW, f, 0);
		}

		private bool capPreviewRate(IntPtr lwnd, short wMS)
		{
			return API32.SendMessage(lwnd, API32.WM_CAP_SET_PREVIEWRATE, wMS, 0);
		}

		private bool capSetCallbackOnFrame(IntPtr lwnd, API32.FrameEventHandler lpProc)
		{
			return API32.SendMessage(lwnd, API32.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);
		}

		private bool capSetVideoFormat(IntPtr hCapWnd, ref API32.BITMAPINFO BmpFormat, int CapFormatSize)
		{
			return API32.SendMessage(hCapWnd, API32.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
		}
		private bool capDlgVideoFormat(IntPtr lwnd)
		{
			return API32.SendMessage(lwnd, API32.WM_CAP_DLG_VIDEOFORMAT, 0, 0);
		}
		public void ShowConfigDialog()
		{
			CloseWebcam();
			byte[] lpszName = new byte[100];
			byte[] lpszVer = new byte[100];

			API32.capGetDriverDescriptionA(0, lpszName, 100,lpszVer, 100);
			this.lwndC = API32.capCreateCaptureWindowA(lpszName, API32.WS_VISIBLE + API32.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0);
			
			if (capDriverConnect(this.lwndC ,0))
			{
				capDlgVideoFormat(this.lwndC);
				CloseWebcam();
			}
			else
				throw new Exception("Camera not found");
		}
		private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
		{
			API32.VIDEOHDR videoHeader = new API32.VIDEOHDR();
			byte[] VideoData;
			videoHeader = (API32.VIDEOHDR)API32.GetStructure(lpVHdr, videoHeader);
			VideoData = new byte[videoHeader.dwBytesUsed];
			API32.Copy(videoHeader.lpData, VideoData);
			System.Drawing.Bitmap bmp = new Bitmap(mWidth, mHeight);

			System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, mWidth, mHeight), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            //System.Drawing.Imaging.BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, mWidth, mHeight), ImageLockMode.ReadWrite, PixelFormat.);

			// Copy the data from memory to the Scan0 property of our Bitmap
            
/*            int l = VideoData.Length;
            for (int i = 0; i < l; i++)
            {
                Marshal.WriteByte(bmpData.Scan0, i, VideoData[i]);
            }
 */

            Marshal.Copy(VideoData, 0, bmpData.Scan0, VideoData.Length);

            bmp.UnlockBits(bmpData);
            
			if (this.RecievedFrame != null)
			{
				WebCameraEventArgs e = new WebCameraEventArgs(VideoData, bmp);
				this.RecievedFrame(this,e);
			}

		}

	}
}