VFW的封装类-摄像功能

在上一篇里,简单介绍了windows VFW库的情况,使用VFW处理还是比较简单的,但是也非常不容易控制,而且,即便仔细看文档的介绍,还是要摸着石头过河。


在CodeForge网站上搜了好长时间,总算从网上找到一个以前人写的 VFWImage的工具类,算是完整封装了VFW的宏和API,于是我把我的项目中,和图像、视频采集的程序使用这个类重写了,重写之后,的确控制起来方便多了。


现在把这个类附上,有需要的朋友可以直接下载来使用,使用方式以后慢慢贴上来吧。

使用这个类,可以非常简单,做到在一个窗口(可以是对话框或各类控件)中显示采集到的活动图像,在用户选择“拍照”时,用上一篇博文中的保存JPG的方法,即可保存为JPG图片。

视频的录制稍微麻烦一些,普通的做法,使用VFW 宏,支持直接保存视频文件,但是只支持AVI(太大了),即便设置的压缩和品质很低,15秒还是能达到10M~20M,受不了。最可恶的是,调用VFW录制时,还会向C盘根目录下写一个视频文件??!!

这里我想了一个办法,也许是笨办法,希望朋友们能有以教我一些更好的方法。

不开启VFW的保存视频功能,只打开活动图像的预览。

启动一个线程,在线程中,一张一张采集图像,将图像写入AVI(虽然还是AVI,但是经过处理,不会太大)

从开始采集起始,开始录音,视频采集完成,停止录音,录音写入WAV

将AVI和WAV合成新的AVI


直接上示例:



       HWND hWnd=pDlg->m_VFWImageProc.GetCapWindow();
        CString myfname("e:\\new12222.avi");
        HDC hDisplayDC = GetDC(hWnd);


        CAVI Avi;
        CString csPathName;
        CString csTempPath;

        //没有声音的AVI以及声音WAV保存在临时目录
        TCHAR * pTempPath = csTempPath.GetBufferSetLength(MAX_PATH + 1);
        GetTempPath(MAX_PATH + 1,pTempPath);
        csTempPath.ReleaseBuffer();

        TCHAR * pTempFile = csPathName.GetBufferSetLength(MAX_PATH + 1);
        GetTempFileName(csTempPath,_T("FRC"),0,pTempFile);
        csPathName.ReleaseBuffer();
        CFileStatus FileStatus;
        if (CFile::GetStatus(csPathName,FileStatus))
            CFile::Remove(csPathName);
        csPathName.Replace(_T(".tmp"),_T(".wav"));
 
        CString cswavFile =   csPathName;

        //视频每秒的帧数
        // Open for recording
        Avi.Open(10);
        // Setup capturing the screen
        int cxWidth = 0;//GetSystemMetrics(SM_CXVIRTUALSCREEN);
        int cyHeight = 0;//GetSystemMetrics(SM_CYVIRTUALSCREEN);

        RECT rr;
        ::GetWindowRect( hWnd,&rr);
          cxWidth = rr.right-rr.left;
          cyHeight = rr.bottom-rr.top;
        CRect DIBRect = CRect(0,0,cxWidth,cyHeight);


        // Device dependent bitmap
        CDIBFrame DIB(0,0,8);
        DIB.Init(cxWidth,cyHeight);

        //录音
        MCIDEVICEID id=0;
        MCI_OPEN_PARMS open;
       
        open.lpstrDeviceType=(LPCSTR)MCI_DEVTYPE_WAVEFORM_AUDIO;
        open.lpstrElementName=_T("");
        open.wDeviceID=id;
        mciSendCommand(NULL,MCI_OPEN,MCI_WAIT|MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID
            |MCI_OPEN_ELEMENT,
            (DWORD)(LPVOID)&open);
        id=open.wDeviceID;

        MCI_RECORD_PARMS record;
       
        mciSendCommand(id,MCI_RECORD,NULL,(DWORD)(LPVOID)&record);   


        //开始图像采集
        int frames=0;
        //for (int iFrame = 1;iFrame <= 150;++iFrame)
       
        //外部在需要时停止录制
        while( !stopped )
        {
            // Capture the desktop
            BitBlt(DIB,0,0,DIBRect.Width(),DIBRect.Height (),hDisplayDC,DIBRect.left,DIBRect.top,SRCCOPY);

            // Add a frame
            Avi.AddFrame(DIB);

            //每隔100毫秒采集1此,也就是每秒10帧
            Sleep(100);
            frames++;
 
        }
        CString filename;
        MCI_SAVE_PARMS save;
        save.lpfilename=cswavFile;// "e:\\t1111.wav";// cswavFile;//_T(  fname+"_wav.wav" );
        mciSendCommand(id,MCI_SAVE,MCI_SAVE_FILE|MCI_WAIT,(DWORD)(LPVOID)&save);
        mciSendCommand(id,MCI_CLOSE,NULL,NULL);   
        CString csaviFile = Avi.Close();


        // Delete the dc's
        ReleaseDC(hWnd,hDisplayDC);
   
        合并AVI和WAV
        Merge_Video_And_Sound_File( csaviFile,cswavFile, myfname );





    大体上就是这样,其中使用到了一个CAVI的类,如果有需要的情给我留言,留下邮箱即可。

你可能感兴趣的:(封装)