Shu-Kai Yang's Works
http://shukaiyang.myweb.hinet.net/ English   繁體中文
  Project News     JavaScript Games     Development Tools     Online Courses     Freeware  
  Introduction   API Document   Sample Code

Video Grabber Library

The sample program vdoview.exe is a simple dialog-based MFC application. There is nothing special in its stdafx.h and vdoview.h. Almost the works are done in vdoview.cpp, and they are black and bold in the following code dump. Only the bold statements below should be noticed.

In CVideoApp::InitInstance( ), It calls  CoInitialize(NULL) to enable the COM usage before starting the video capturing. Then in CVideoDlg::OnInitDialog( ),  it calls GrabberOpen( ) to connect the camera together with a call function GrabberCallback( ). A bitmap header is prepared to render the received image in CVideoDlg class. After the starting button is clicked, GrabberStart( ) is called, and the video capturing runs. So the callback  function GrabberCallback( ) is invoked continuously. It copies the received image to pDlg->pBits and request re-display.

vdoview.h

/** @file vdoview.h
  * @brief Declarations.

  * The file declares the dialog and application classes of this dialog-based
    program that demonstrates the usage of vdograb.lib.

  * @author Shu-Kai Yang (http://shukaiyang.myweb.hinet.net/)
  * @date 2006/11/25 */

#include "resource.h" // main symbols

#define DEVICE_NAME NULL
// #define DEVICE_NAME L"USB 2.0 1.3M UVC WebCam"

class CVideoApp : public CWinApp
{
    // Overrides
    public:
    virtual BOOL InitInstance();

    // Implementation:
    DECLARE_MESSAGE_MAP()
};

// CVideoDlg dialog
class CVideoDlg : public CDialog
{
    public:
    // Dialog Data:
    enum { IDD = IDD_VDOVIEW_DIALOG };

    BITMAPINFOHEADER header;
    LPBYTE pBits;

    protected:
    HICON m_hIcon;

    // Construction
    public:
    CVideoDlg(CWnd * pParent = NULL);

    // Implementation
    protected:
    // Generated message map functions
    virtual BOOL OnInitDialog();
    afx_msg void OnDestroy();
    afx_msg void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    afx_msg void OnBnClickedStart();
    afx_msg void OnBnClickedStop();
    DECLARE_MESSAGE_MAP()
};

vdoview.cpp

/** @file vdoview.cpp
 * @brief Implementations.

 * The file implements the dialog and application classes of the dialog-based
   application that demonstrates the usage of vdograb.dll. When the dialog is
   being initialized, it opened the video-capturing device (web camera). Then
   when the user clicks the "Start" button, the dialog receives the captured
   images via the callback function and renders the images. 

 * @author Shu-Kai Yang (http://shukaiyang.myweb.hinet.net/)
 * @date 2006/11/26 */

#include "stdafx.h"
#include "vdoview.h"
#include "../vdograb/vdograb.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

// The one and only CVideoApp object:
CVideoApp theApp;
void GrabberCallback(void *, int, int, int);

// CVideoApp message map:
BEGIN_MESSAGE_MAP(CVideoApp, CWinApp)
END_MESSAGE_MAP()

// CVideoApp initialization"
BOOL CVideoApp::InitInstance()
{
    // Typical MFC initializations:
    INITCOMMONCONTROLSEX InitCtrls;
    InitCtrls.dwSize = sizeof(InitCtrls);
    InitCtrls.dwICC = ICC_WIN95_CLASSES;
    InitCommonControlsEx(&InitCtrls);

    CWinApp::InitInstance();
    CoInitialize(NULL);

    // Disaplay a dialog and set it the main window of the application:
    CVideoDlg dlg;
    m_pMainWnd = &dlg;
    dlg.DoModal();

    CoUninitialize();
    return FALSE;
}

// CVideoDlg dialog
CVideoDlg::CVideoDlg(CWnd * pParent) : CDialog(CVideoDlg::IDD, pParent), pBits(NULL)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

    // Fill the dummy bitmap header for DIB rendering:
    header.biSize = sizeof(BITMAPINFOHEADER);
    header.biPlanes = 1;
    header.biBitCount = 24;
    header.biCompression = BI_RGB;
    header.biXPelsPerMeter = 120;
    header.biYPelsPerMeter = 120;
    header.biClrUsed = 0;
    header.biClrImportant = 0;
}

BEGIN_MESSAGE_MAP(CVideoDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_START, &CVideoDlg::OnBnClickedStart)
ON_BN_CLICKED(IDC_STOP, &CVideoDlg::OnBnClickedStop)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// CVideoDlg message handlers:
BOOL CVideoDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set the icon for this dialog:
    SetIcon(m_hIcon, TRUE);
    SetIcon(m_hIcon, FALSE);

    // Enable the video capturing at beginning:
    if (GrabberOpen(DEVICE_NAME, GrabberCallback) == FALSE)
    {  AfxMessageBox(L"Can not open the camera device!", MB_ICONSTOP | MB_OK);
    return FALSE; }

    return TRUE;
}

void CVideoDlg::OnDestroy()
{
    // Stop the video capturing when closing the window:
    GrabberClose();
    if (pBits) {  delete pBits;  }

    CDialog::OnDestroy();
}

// The system calls this function to obtain the cursor to display
// while the user drags the minimized window.
HCURSOR CVideoDlg::OnQueryDragIcon()
{   return static_cast<HCURSOR>(m_hIcon);  }

void CVideoDlg::OnBnClickedStart()
{
    if(GrabberStart() == FALSE)
    {   AfxMessageBox(L"Can not start the video capturing!", MB_ICONSTOP | MB_OK);  }
}

void CVideoDlg::OnBnClickedStop()
{   GrabberStop();  }

void CVideoDlg::OnPaint()
{
    CRect rect;

    if (IsIconic())
    {
        // If you add a minimize button to your dialog, you will need the code below to draw the
        // icon. For MFC applications using the document/view model, this is automatically done
        // for you by the framework.
        CPaintDC dc(this);
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

        // Center icon in client rectangle:
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);

        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1) / 2;
        int y = (rect.Height() - cyIcon + 1) / 2;

        // Draw the icon:
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        CDialog::OnPaint();

        // The captured data is already a bottom-up DIB image, so stretch it:
        CWnd * pCanvas = GetDlgItem(IDC_CANVAS);
        if((pCanvas) && (pBits))
        {
            CPaintDC dc(pCanvas);
            dc.SetStretchBltMode(HALFTONE);
            pCanvas->GetClientRect(&rect);
            ::StretchDIBits(dc.GetSafeHdc(), 0, 0, rect.Width(), rect.Height(),
                0, 0, header.biWidth, header.biHeight, pBits, (BITMAPINFO *)&header,
                DIB_RGB_COLORS, SRCCOPY);
        }
    }
}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Callback Function for the Library:
void GrabberCallback(void * pBits, int width, int height, int size)
{
    // Get the dialog window and Retrieve the canvas window for rendering:
    CVideoDlg * pDlg = (CVideoDlg *)(theApp.m_pMainWnd);
    if(pDlg == NULL) { return; }

    TRACE(L"GrabberCallback(%dx%d, %d bytes)\n", width, height, size);

    // Fill bitmap header for DIB rendering:
    pDlg->header.biWidth = width;
    pDlg->header.biHeight = height;
    pDlg->header.biSizeImage = size;

    // Copy the pixels to the dialog, allocating the memory when necessary:
    if (pDlg->pBits == NULL) { pDlg->pBits = new BYTE[size]; }
    if (pDlg->pBits) { memcpy(pDlg->pBits, pBits, size); }
    pDlg->Invalidate(FALSE);
}

Last updated at 2006 / 11 / 27 by Shu-Kai Yang.

You are the th visitor since 2008 January.