MFC vfw視頻捕獲

// VideoImage_lzyView.cpp : implementation of the CVideoImage_lzyView class
//

#include "stdafx.h"
// SHARED_HANDLERS can be defined in an ATL project implementing preview, thumbnail
// and search filter handlers and allows sharing of document code with that project.
#ifndef SHARED_HANDLERS
#include "VideoImage_lzy.h"
#endif

#include "VideoImage_lzyDoc.h"
#include "VideoImage_lzyView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

//全局變量
static DWORD AVIwidth = 639;	//640 480 溢出錯誤;639 479及以下就沒有錯誤
static DWORD AVIheight = 479;	//但是SDK裏面正常  http://blog.csdn.net/lzy2014/article/details/27558901
HBITMAP hBmpScene;
HDC hdcScene = NULL;
CDC* pDC;
// CVideoImage_lzyView

IMPLEMENT_DYNCREATE(CVideoImage_lzyView, CView)

BEGIN_MESSAGE_MAP(CVideoImage_lzyView, CView)
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
	ON_COMMAND(IDM_BMP_CAP, &CVideoImage_lzyView::OnBmpCap)
	ON_COMMAND(IDM_BMP_SAVE, &CVideoImage_lzyView::OnBmpSave)
//	ON_WM_SIZE()
END_MESSAGE_MAP()

// CVideoImage_lzyView construction/destruction

CVideoImage_lzyView::CVideoImage_lzyView()
{
	// TODO: add construction code here
	hWndCap = NULL;		//構造函數中將其初始化
}

CVideoImage_lzyView::~CVideoImage_lzyView()
{
}

BOOL CVideoImage_lzyView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

// CVideoImage_lzyView drawing

void CVideoImage_lzyView::OnDraw(CDC* /*pDC*/)
{
	CVideoImage_lzyDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	if (!pDoc)
		return;

	// TODO: add draw code for native data here


}


// CVideoImage_lzyView printing

BOOL CVideoImage_lzyView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CVideoImage_lzyView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CVideoImage_lzyView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}


// CVideoImage_lzyView diagnostics

#ifdef _DEBUG
void CVideoImage_lzyView::AssertValid() const
{
	CView::AssertValid();
}

void CVideoImage_lzyView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CVideoImage_lzyDoc* CVideoImage_lzyView::GetDocument() const // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CVideoImage_lzyDoc)));
	return (CVideoImage_lzyDoc*)m_pDocument;
}
#endif //_DEBUG


// CVideoImage_lzyView message handlers


//視頻捕獲函數
void CVideoImage_lzyView::OnBmpCap()
{
	// TODO: Add your command handler code here
	//獲取客戶區大小
	CRect clientRect;
	GetClientRect(&clientRect);

	//創建圖像採集窗口
	hWndCap = capCreateCaptureWindow(TEXT("採集圖像"), WS_CHILD | WS_VISIBLE, 0, 0,
		AVIwidth, AVIheight, m_hWnd, 1);	//注意最後一個參數
	if (! hWndCap)
	{
		MessageBox(TEXT("圖像採集窗口創建失敗!"));
		return;
	}

	BITMAPINFO bmpInfo;
	HGDIOBJ hGDIObj;

	//DIB結構體的各種屬性設置  
	ZeroMemory(&bmpInfo.bmiHeader, sizeof(BITMAPINFOHEADER));  
	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);  
	bmpInfo.bmiHeader.biBitCount = 24;  
	bmpInfo.bmiHeader.biWidth = AVIwidth;  
	bmpInfo.bmiHeader.biHeight = AVIheight;  
	bmpInfo.bmiHeader.biPlanes = 1;  
	bmpInfo.bmiHeader.biClrUsed = 0;  
	bmpInfo.bmiHeader.biClrImportant = 0;  
	bmpInfo.bmiHeader.biSizeImage = AVIwidth * AVIheight * bmpInfo.bmiHeader.biBitCount / 8;  

	//創建應用程序可以直接寫入的、與設備無關的位圖(DIB) 
	pDC = this->GetDC();
	hdcScene = CreateCompatibleDC(pDC->m_hDC);  
	hBmpScene = CreateDIBSection(hdcScene, &bmpInfo, DIB_RGB_COLORS, NULL, 0, 0);  
	hGDIObj = SelectObject(hdcScene, hBmpScene);

	//設置回調函數
	capSetCallbackOnFrame(hWndCap, &FrameCallbackProc);

	//連接視頻採集設備
	if (! capDriverConnect(hWndCap, 0))		//注意:第二個參數是攝像頭索引號(含有多個攝像頭需注意);第二個參數  調試!!!!!!!
	{
		MessageBox(TEXT("視頻採集設備連接失敗!"));
		return;
	}
	//設置視頻預覽的圖像大小 和 頻率
	capPreviewRate(hWndCap, 30);
	capPreviewScale(hWndCap, TRUE);	//第二個參數  調試!!!!!!!

	SelectObject(hdcScene, hGDIObj);  
	DeleteObject(hBmpScene); 
	DeleteDC(hdcScene);
}


//圖像保存函數
void CVideoImage_lzyView::OnBmpSave()
{
	// TODO: Add your command handler code here
	if (! capFileSaveDIB(hWndCap, TEXT("save.bmp")))
	{
		MessageBox(TEXT("圖像保存失敗!"));
		return;
	}
}


LRESULT CVideoImage_lzyView::FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr)
{
	long cB, cG, cR;  
	long X, Y;
	long OutputWidth = AVIwidth * 3;  
	long InputWidth = AVIwidth * 3;
	BYTE BmpByte[1920*480];

	for (Y = 1; Y <= AVIheight; Y++)  
    {  
        for (X = 1; X <= AVIwidth; X++)  
        {  
			
            cB = lpVHdr->lpData[((AVIheight-Y)*InputWidth)+(X*3)];  
            cG = lpVHdr->lpData[((AVIheight-Y)*InputWidth)+(X*3)+1];  
            cR = lpVHdr->lpData[((AVIheight-Y)*InputWidth)+(X*3)+2];  
            BmpByte[((Y-1)*OutputWidth)+(X*3)]=cB;  
            BmpByte[((Y-1)*OutputWidth)+(X*3)+1]=cG;  
            BmpByte[((Y-1)*OutputWidth)+(X*3)+2]=cR; 
			/*if (X == 160 && Y == 120)
			{
				system("pause");	//查看數據是否有變化
			}*/
        }
    } 
	long i = sizeof(BmpByte);
	long i2 = SetBitmapBits(hBmpScene, sizeof(BmpByte), BmpByte);	//成功後,返回值表示字節數;失敗爲0.
	
    BitBlt(pDC->m_hDC, 0, 0, AVIwidth, AVIheight, hdcScene, 0, 0, SRCCOPY);

	//一個現象就是,視頻不動,但是不停地改變窗口大小(拖動窗口右下角)時,視頻動了;
	//說明需要重繪,invalidate
	//但是,static函數(回調函數)裏面不能直接調用Invalidate函數
	//需要通過GetActiveWindow  FindWindow 等等獲取view類窗口句柄
	GetActiveWindow()->Invalidate(TRUE);
	//成功後,閃屏厲害;要用到雙緩衝
    return 0;
}


都是在CView類裏面   

在菜單裏面增加的兩個菜單命令響應函數(視類)  

頭文件如下:

只增加了窗口句柄hWndCap和回調函數

// VideoImage_lzyView.h : interface of the CVideoImage_lzyView class
//

#pragma once


class CVideoImage_lzyView : public CView
{
protected: // create from serialization only
	CVideoImage_lzyView();
	DECLARE_DYNCREATE(CVideoImage_lzyView)

// Attributes
public:
	CVideoImage_lzyDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
	virtual void OnDraw(CDC* pDC);  // overridden to draw this view
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
	virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
	virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);

// Implementation
public:
	virtual ~CVideoImage_lzyView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	DECLARE_MESSAGE_MAP()
private:
	HWND hWndCap;
public:
	afx_msg void OnBmpCap();
	afx_msg void OnBmpSave();
	static LRESULT FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVHdr);
//	afx_msg void OnSize(UINT nType, int cx, int cy);
};

#ifndef _DEBUG  // debug version in VideoImage_lzyView.cpp
inline CVideoImage_lzyDoc* CVideoImage_lzyView::GetDocument() const
   { return reinterpret_cast<CVideoImage_lzyDoc*>(m_pDocument); }
#endif

還需要優化變量,如何安排或者抽象到類。


發佈了28 篇原創文章 · 獲贊 7 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章