实例介绍
【实例简介】解决某些Windows 7下不能拍照问题。
【实例截图】
【核心代码】
public partial class frmCamera : Form, ISampleGrabberCB { #region 私有变量 /// <summary> /// 保存抓拍的图片 /// </summary> Image theImage = null; /// <summary> /// 需要重新抓拍的状态 /// </summary> bool _reclap = false; /// <summary> /// 摄像头的状态 /// </summary> bool _cameraIsStart = false; /// <summary> /// base filter of the actually used video devices. /// </summary> private IBaseFilter capFilter; /// <summary> /// graph builder interface. /// </summary> private IGraphBuilder graphBuilder; /// <summary> /// capture graph builder interface. /// </summary> private ICaptureGraphBuilder2 capGraph; private ISampleGrabber sampGrabber; /// <summary> /// control interface. /// </summary> private IMediaControl mediaCtrl; /// <summary> event interface. </summary> private IMediaEventEx mediaEvt; /// <summary> video window interface. </summary> private IVideoWindow videoWin; /// <summary> grabber filter interface. </summary> private IBaseFilter baseGrabFlt; /// <summary> structure describing the bitmap to grab. </summary> private VideoInfoHeader videoInfoHeader; private bool captured = true; private int bufferedSize; /// <summary> /// buffer for bitmap data. /// </summary> private byte[] savedArray; /// <summary> /// list of installed video devices. /// </summary> private ArrayList capDevices; private const int WM_GRAPHNOTIFY = 0x00008001; // message from graph private const int WS_CHILD = 0x40000000; // attributes for video window private const int WS_CLIPCHILDREN = 0x02000000; private const int WS_CLIPSIBLINGS = 0x04000000; /// <summary> /// event when callback has finished (ISampleGrabberCB.BufferCB). /// </summary> private delegate void CaptureDone(); #if DEBUG private int rotCookie = 0; #endif #endregion #region 私有函数 /// <summary> /// capture event, triggered by buffer callback. /// </summary> void OnCaptureDone() { Trace.WriteLine("!!DLG: OnCaptureDone"); try { int hr; if (sampGrabber == null) return; hr = sampGrabber.SetCallback(null, 0); int w = videoInfoHeader.BmiHeader.Width; int h = videoInfoHeader.BmiHeader.Height; if (((w & 0x03) != 0) || (w < 32) || (w > 4096) || (h < 32) || (h > 4096)) return; int stride = w * 3; GCHandle handle = GCHandle.Alloc(savedArray, GCHandleType.Pinned); int scan0 = (int)handle.AddrOfPinnedObject(); scan0 = (h - 1) * stride; Bitmap b = new Bitmap(w, h, -stride, System.Drawing.Imaging.PixelFormat.Format24bppRgb, (IntPtr)scan0); handle.Free(); savedArray = null; Image old = pbPicture.Image; pbPicture.Image = b; if (old != null) old.Dispose(); } catch (Exception ee) { MessageBox.Show(this, "Could not grab picture\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); } } /// <summary> /// start all the interfaces, graphs and preview window. /// </summary> bool StartupVideo(UCOMIMoniker mon) { int hr; try { if (!CreateCaptureDevice(mon)) return false; if (!GetInterfaces()) return false; if (!SetupGraph()) return false; if (!SetupVideoWindow()) return false; #if DEBUG DsROT.AddGraphToRot(graphBuilder, out rotCookie); // graphBuilder capGraph #endif hr = mediaCtrl.Run(); if (hr < 0) Marshal.ThrowExceptionForHR(hr); bool hasTuner = DsUtils.ShowTunerPinDialog(capGraph, capFilter, this.Handle); return true; } catch (Exception ee) { MessageBox.Show(this, "Could not start video stream\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } } /// <summary> /// make the video preview window to show in videoPanel. /// </summary> bool SetupVideoWindow() { int hr; try { // Set the video window to be a child of the main window hr = videoWin.put_Owner(pbCamera.Handle); if (hr < 0) Marshal.ThrowExceptionForHR(hr); // Set video window style hr = videoWin.put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); if (hr < 0) Marshal.ThrowExceptionForHR(hr); // Use helper function to position video window in client rect of owner window ResizeVideoWindow(); // Make the video window visible, now that it is properly positioned hr = videoWin.put_Visible(DsHlp.OATRUE); if (hr < 0) Marshal.ThrowExceptionForHR(hr); hr = mediaEvt.SetNotifyWindow(this.Handle, WM_GRAPHNOTIFY, IntPtr.Zero); if (hr < 0) Marshal.ThrowExceptionForHR(hr); return true; } catch (Exception ee) { MessageBox.Show(this, "Could not setup video window\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } } /// <summary> /// build the capture graph for grabber. /// </summary> bool SetupGraph() { int hr; try { hr = capGraph.SetFiltergraph(graphBuilder); if (hr < 0) Marshal.ThrowExceptionForHR(hr); hr = graphBuilder.AddFilter(capFilter, "Ds.NET Video Capture Device"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); DsUtils.ShowCapPinDialog(capGraph, capFilter, this.Handle); AMMediaType media = new AMMediaType(); media.majorType = MediaType.Video; media.subType = MediaSubType.RGB24; media.formatType = FormatType.VideoInfo; // ??? hr = sampGrabber.SetMediaType(media); if (hr < 0) Marshal.ThrowExceptionForHR(hr); hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber"); if (hr < 0) Marshal.ThrowExceptionForHR(hr); Guid cat = PinCategory.Preview; Guid med = MediaType.Video; hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, null); // baseGrabFlt if (hr < 0) Marshal.ThrowExceptionForHR(hr); cat = PinCategory.Capture; med = MediaType.Video; hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, baseGrabFlt); // baseGrabFlt if (hr < 0) Marshal.ThrowExceptionForHR(hr); media = new AMMediaType(); hr = sampGrabber.GetConnectedMediaType(media); if (hr < 0) Marshal.ThrowExceptionForHR(hr); if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero)) throw new NotSupportedException("Unknown Grabber Media Format"); videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader)); Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero; hr = sampGrabber.SetBufferSamples(false); if (hr == 0) hr = sampGrabber.SetOneShot(false); if (hr == 0) hr = sampGrabber.SetCallback(null, 0); if (hr < 0) Marshal.ThrowExceptionForHR(hr); return true; } catch (Exception ee) { MessageBox.Show(this, "Could not setup graph\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } } /// <summary> /// create the used COM components and get the interfaces. /// </summary> bool GetInterfaces() { Type comType = null; object comObj = null; try { comType = Type.GetTypeFromCLSID(Clsid.FilterGraph); if (comType == null) throw new NotImplementedException(@"DirectShow FilterGraph not installed/registered!"); comObj = Activator.CreateInstance(comType); graphBuilder = (IGraphBuilder)comObj; comObj = null; Guid clsid = Clsid.CaptureGraphBuilder2; Guid riid = typeof(ICaptureGraphBuilder2).GUID; comObj = DsBugWO.CreateDsInstance(ref clsid, ref riid); capGraph = (ICaptureGraphBuilder2)comObj; comObj = null; comType = Type.GetTypeFromCLSID(Clsid.SampleGrabber); if (comType == null) throw new NotImplementedException(@"DirectShow SampleGrabber not installed/registered!"); comObj = Activator.CreateInstance(comType); sampGrabber = (ISampleGrabber)comObj; comObj = null; mediaCtrl = (IMediaControl)graphBuilder; videoWin = (IVideoWindow)graphBuilder; mediaEvt = (IMediaEventEx)graphBuilder; baseGrabFlt = (IBaseFilter)sampGrabber; return true; } catch (Exception ee) { MessageBox.Show(this, "Could not get interfaces\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } finally { if (comObj != null) Marshal.ReleaseComObject(comObj); comObj = null; } } /// <summary> /// create the user selected capture device. /// </summary> bool CreateCaptureDevice(UCOMIMoniker mon) { object capObj = null; try { Guid gbf = typeof(IBaseFilter).GUID; mon.BindToObject(null, null, ref gbf, out capObj); capFilter = (IBaseFilter)capObj; capObj = null; return true; } catch (Exception ee) { MessageBox.Show(this, "Could not create capture device\r\n" ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); return false; } finally { if (capObj != null) Marshal.ReleaseComObject(capObj); capObj = null; } } /// <summary> /// 关闭摄像头 释放资源 /// </summary> void stopCamera() { int hr; try { #if DEBUG if (rotCookie != 0) DsROT.RemoveGraphFromRot(ref rotCookie); #endif if (mediaCtrl != null) { hr = mediaCtrl.Stop(); mediaCtrl = null; } if (mediaEvt != null) { hr = mediaEvt.SetNotifyWindow(IntPtr.Zero, WM_GRAPHNOTIFY, IntPtr.Zero); mediaEvt = null; } if (videoWin != null) { hr = videoWin.put_Visible(DsHlp.OAFALSE); hr = videoWin.put_Owner(IntPtr.Zero); videoWin = null; } baseGrabFlt = null; if (sampGrabber != null) Marshal.ReleaseComObject(sampGrabber); sampGrabber = null; if (capGraph != null) Marshal.ReleaseComObject(capGraph); capGraph = null; if (graphBuilder != null) Marshal.ReleaseComObject(graphBuilder); graphBuilder = null; if (capFilter != null) Marshal.ReleaseComObject(capFilter); capFilter = null; if (capDevices != null) { foreach (DsDevice d in capDevices) d.Dispose(); capDevices = null; } } catch (Exception) { } } /// <summary> /// resize preview video window to fill client area. /// </summary> void ResizeVideoWindow() { if (videoWin != null) { Rectangle rc = pbCamera.ClientRectangle; videoWin.SetWindowPosition(0, 0, rc.Right, rc.Bottom); } } /// <summary> /// graph event (WM_GRAPHNOTIFY) handler. /// </summary> void OnGraphNotify() { DsEvCode code; int p1, p2, hr = 0; do { hr = mediaEvt.GetEvent(out code, out p1, out p2, 0); if (hr < 0) break; hr = mediaEvt.FreeEventParams(code, p1, p2); } while (hr == 0); } /// <summary> /// 启动摄像头 /// </summary> private void startCamera() { if (!DsUtils.IsCorrectDirectXVersion())//检查DirectX版本 { MessageBox.Show(this, "DirectX 8.1 NOT installed!", "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); this.Close(); return; } //检查摄像头设备 if (!DsDev.GetDevicesOfCat(FilterCategory.VideoInputDevice, out capDevices)) { MessageBox.Show(this, "No video capture devices found!", "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop); this.Close(); return; } //如果只有一个摄像头设备,则直接指定设备;若不止一个,则弹出设备列表,选择一个 DsDevice dev = null; if (capDevices.Count == 1) dev = capDevices[0] as DsDevice; else { frmCameraSelector selector = new frmCameraSelector(capDevices); selector.ShowDialog(this); dev = selector.SelectedDevice; } if (dev == null) { this.Close(); return; } //开始视频 if (!StartupVideo(dev.Mon)) this.Close(); } #endregion #region 接口实现 /// <summary> sample callback, NOT USED. </summary> int ISampleGrabberCB.SampleCB(double SampleTime, IMediaSample pSample) { Trace.WriteLine("!!CB: ISampleGrabberCB.SampleCB"); return 0; } /// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary> int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen) { if (captured || (savedArray == null)) { Trace.WriteLine("!!CB: ISampleGrabberCB.BufferCB"); return 0; } captured = true; bufferedSize = BufferLen; Trace.WriteLine("!!CB: ISampleGrabberCB.BufferCB !GRAB! size = " BufferLen.ToString()); if ((pBuffer != IntPtr.Zero) && (BufferLen > 1000) && (BufferLen <= savedArray.Length)) Marshal.Copy(pBuffer, savedArray, 0, BufferLen); else Trace.WriteLine(" !!!GRAB! failed "); this.BeginInvoke(new CaptureDone(this.OnCaptureDone)); return 0; } #endregion #region 构造 public frmCamera() { InitializeComponent(); } #endregion #region 事件 /// <summary> /// 重些 处理图像事件 /// </summary> protected override void WndProc(ref Message m) { if (m.Msg == WM_GRAPHNOTIFY) { if (mediaEvt != null) OnGraphNotify(); return; } base.WndProc(ref m); } /// <summary> /// 启动或关闭摄像头 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnStart_Click(object sender, EventArgs e) { if (!_cameraIsStart) { pbPicture.SendToBack(); startCamera(); _cameraIsStart = true; btnStart.Text = "关闭摄像头"; btnClap.Text = "拍照"; } else { stopCamera(); btnStart.Text = "启动摄像头"; btnClap.Text = "拍照"; _cameraIsStart = false; _reclap = false; } } /// <summary> /// 拍照 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnClap_Click(object sender, EventArgs e) { if (_cameraIsStart == true) { if (_reclap == false) { Trace.WriteLine("!!BTN: toolBarBtnGrab"); if (savedArray == null) { int size = videoInfoHeader.BmiHeader.ImageSize; if ((size < 1000) || (size > 16000000)) return; savedArray = new byte[size 64000]; } Image old = pbPicture.Image; pbPicture.Image = null; if (old != null) old.Dispose(); captured = false; int hr = sampGrabber.SetCallback(this, 1); pbPicture.Image = theImage; pbCamera.SendToBack(); _reclap = true; btnClap.Text = "重拍"; } else { pbPicture.SendToBack(); btnClap.Text = "拍照"; _reclap = false; } } } #endregion [STAThread] static void Main() { Application.Run(new frmCamera()); } }
标签: 拍照
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论