// 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
還需要優化變量,如何安排或者抽象到類。