李国帅 2015/3/27 10:46:31
在使用directshow进行抓图的时候,存在两难:
如果在转换过滤器抓图,那么可能因为某些原因无法抓到真实的图片。
如果使用directx的vmr9抓图,可能效率比较低,m_pVmrWC->GetCurrentImage(&pDataBuffer);//大概需要3秒钟
但现在也只能使用vmr抓图了。
#include <Gdiplus.h> #include <GdiplusHeaders.h> #include <GdiplusImaging.h> #pragma comment(lib,"gdiplus.lib.") using namespace Gdiplus; LONG VMR9::TakeSnapshot(LPCTSTR outFile) { //CNetLog::printlog(0,_T("%s begin.\n"),__FUNCTIONT__); CheckPointer(m_pVmrWC, E_POINTER); BYTE *pDataBuffer = NULL; HRESULT hr = m_pVmrWC->GetCurrentImage(&pDataBuffer);//大概需要3秒钟 BITMAPINFOHEADER *lpbi = (BITMAPINFOHEADER *)pDataBuffer; if (!SUCCEEDED(hr)) { CNetLog::printlog(0, _T("%s TakeSnapshot failed.\n"), __FUNCTIONT__); return S_FALSE; } LONG nRet = SavePicture(outFile, lpbi, pDataBuffer); CoTaskMemFree(pDataBuffer);//释放资源 return nRet; } LONG CVideoRenderer::SavePicture(LPCTSTR outFile, BITMAPINFOHEADER * lpbi, BYTE * pDataBuffer) { LONG nRet = 0; int nColors = 1 << lpbi->biBitCount; if (nColors > 256)nColors = 0; DWORD dwBitmapSize = 0; dwBitmapSize = nColors * sizeof(RGBQUAD)+lpbi->biSizeImage;//biSizeImage中包含 sizeof(BITMAPINFOHEADER) DWORD bOffBits = lpbi->biSize + nColors * sizeof(RGBQUAD); BITMAPFILEHEADER hdrFile; hdrFile.bfType = ((WORD)('M' << 8) | 'B'); // always is "BM" hdrFile.bfSize = sizeof(BITMAPFILEHEADER)+dwBitmapSize; hdrFile.bfOffBits = (DWORD)(sizeof(BITMAPFILEHEADER)+bOffBits); hdrFile.bfReserved1 = 0; hdrFile.bfReserved2 = 0; CLSID clsid;//图像存储 jpg GetCodecClsid(L"image/jpeg", &clsid); //TCHAR* JpgFile = _T("e:\\test.jpg");//添加扩展名 void* pbmpData = pDataBuffer + sizeof(BITMAPINFOHEADER)+nColors * sizeof(RGBQUAD); Bitmap *pBmp = Bitmap::FromBITMAPINFO((BITMAPINFO*)pDataBuffer, pbmpData); nRet = pBmp->Save(outFile, &clsid); CNetLog::printlog(0, _T("%s OK. ImgFile=%s\n"), __FUNCTIONT__, outFile); return nRet; } void CVideoRenderer::GetCodecClsid(const WCHAR* format, CLSID* pClsid) { UINT codenum = 0; UINT size = 0; Gdiplus::ImageCodecInfo* pImageCodecInfo = NULL; GetImageEncodersSize(&codenum, &size); if (size == 0) return; pImageCodecInfo = new ImageCodecInfo[size]; if (pImageCodecInfo == NULL) return; GetImageEncoders(codenum, size, pImageCodecInfo); for (UINT j = 0; j < codenum; ++j) { if (wcscmp(pImageCodecInfo[j].MimeType, format) == 0) { *pClsid = pImageCodecInfo[j].Clsid; delete[]pImageCodecInfo; return; } } delete[]pImageCodecInfo; return; }