天天看點

對軟體客戶區進行視訊錄制,采用截圖+壓縮至avi的做法壓縮代碼

https://blog.csdn.net/immortal_mcl

壓縮代碼:

void CRobotAppView::OnTimer(UINT_PTR nIDEvent)

{

// TODO: 在此添加消息處理程式代碼和/或調用預設值

if(m_timer)//如果上一次的定時器程式已經運作完,才執行下面的代碼

{

m_timer=FALSE;//本次定時,正在運作,未結束前,不得進行下次運作

CView* pView;

CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->GetMainWnd();

  CMDIChildWnd *pChild = (CMDIChildWnd*)pFrame->GetActiveFrame();

  pView = (CRobotAppView*)pChild->GetActiveView();

CRect rc;

pView->GetWindowRect(rc);

         CDC * pClientDC =pView->GetDC();

CDC  memDC;//定義一個記憶體畫布

memDC.CreateCompatibleDC(pClientDC);//建立一個相容的畫布

CBitmap bmp;

bmp.CreateCompatibleBitmap(pClientDC,rc.Width(),rc.Height());//建立相容位圖

memDC.SelectObject(&bmp);//選中位圖對象

BITMAP bitmap;

bmp.GetBitmap(&bitmap);

CDC* pDeskDC =GetDesktopWindow()->GetDC();//擷取桌面畫布對象  擷取桌面視窗上下文環境的指針(句柄)

memDC.BitBlt(0,0,bitmap.bmWidth,bitmap.bmHeight,pDeskDC,rc.left,rc.top,SRCCOPY);

DWORD size=bitmap.bmWidthBytes * bitmap.bmHeight;//螢幕圖像的總像素數

lpData = new BYTE[size];

int panelsize  = 0; //記錄調色闆大小

if(bitmap.bmBitsPixel<16)//判斷是否為真彩色位圖

panelsize = (int)pow((float)2,(int)(bitmap.bmBitsPixel*sizeof(RGBQUAD)));

//填充BITMAPFILEHEADER

BITMAPFILEHEADER bitmapFileHeader;

memset(&bitmapFileHeader,0,sizeof(BITMAPFILEHEADER));

bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);

bitmapFileHeader.bfType = 0x4d42; //BM

bitmapFileHeader.bfOffBits =sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

BITMAPINFOHEADER *pBInfo = new BITMAPINFOHEADER;//定義位圖資訊頭結構體

//初始化位圖資訊頭

pBInfo->biBitCount       = bitmap.bmBitsPixel;

pBInfo->biClrImportant   = 0;

pBInfo->biCompression    = 0;

pBInfo->biHeight         = bitmap.bmHeight;

pBInfo->biPlanes         = bitmap.bmPlanes;

pBInfo->biSize           = sizeof(BITMAPINFOHEADER);

pBInfo->biSizeImage      = bitmap.bmWidthBytes*bitmap.bmHeight;

pBInfo->biWidth          = bitmap.bmWidth;

pBInfo->biXPelsPerMeter  = 0;

pBInfo->biYPelsPerMeter  = 0;

BITMAPINFO bInfo;//定義位圖資訊結構體

bInfo.bmiHeader = *pBInfo;//初始化

GetDIBits(memDC.m_hDC,bmp,0, pBInfo->biHeight,lpData,&bInfo,DIB_RGB_COLORS);// 擷取螢幕位圖的DIB資料(生成avi需要),儲存到lpdata

if(nFrames == 0)//如果是第一幀

{

AVISTREAMINFO strhdr;//視訊資料流結構

AVIFileOpen(&pfile,m_VedioName,OF_WRITE | OF_CREATE,NULL);//打開或建立AVI檔案

/初始化AVI視訊流資訊結構體

memset(&strhdr, 0, sizeof(strhdr));//初始化資訊頭為0

strhdr.fccType    = streamtypeVIDEO;

strhdr.fccHandler = mmioStringToFOURCC(_T("MSVC"), 0);  

strhdr.dwScale    = 1;

strhdr.dwRate     = m_VedioFrame;

strhdr.dwSuggestedBufferSize = pBInfo->biSizeImage;

SetRect(&strhdr.rcFrame,0,0,pBInfo->biWidth,pBInfo->biHeight);

AVIFileCreateStream(pfile,&pS,&strhdr);//建立AVI檔案流

//設定壓縮選項,建立壓縮流 

AVICOMPRESSOPTIONS pCompressOption;   

AVICOMPRESSOPTIONS* opts[1] = {&pCompressOption}; 

memset(&pCompressOption,0,sizeof(pCompressOption));

opts[0]->fccType = streamtypeVIDEO;

opts[0]->fccHandler = mmioStringToFOURCC(_T("MSVC"), 0);

opts[0]->dwQuality = 10000;//original :7500

opts[0]->dwBytesPerSecond = 1000;//original :0

opts[0]->dwFlags = AVICOMPRESSF_VALID || AVICOMPRESSF_KEYFRAMES;

opts[0]->lpFormat = 0;

opts[0]->cbFormat = 0;

AVIMakeCompressedStream(&pComStream,pS,&pCompressOption,NULL); 

AVIStreamSetFormat(pComStream,0,pBInfo,sizeof(BITMAPINFOHEADER));

}

AVIStreamWrite(pComStream,nFrames ,1,(LPBYTE)lpData,pBInfo->biSizeImage,AVIIF_KEYFRAME,NULL,NULL);//将桌面圖像資料寫入檔案

nFrames++;//增加一幀

delete []lpData;//釋放記憶體

delete pBInfo ; //釋放記憶體

ReleaseDC(pClientDC);

ReleaseDC(pDeskDC);

ReleaseDC(&memDC);

m_timer=TRUE;//定時器程式可以繼續響應

}

CBaseView::OnTimer(nIDEvent);

}