How To: Save image to BMP file from IBasicVideo or VMR windowless interface

A simple question being asked all over again. Given IBasicVideo, IBasicVideo2, IVMRWindowlessControl or IVMRWindowlessControl9, how to save image to file? It is easy. It is a bit easier with IBasicVideo because it is possible to query this interface directly from graph’s interface, such as IGraphBuilder, and the call will be forwarded to video renderer. This code assumes internal bitmap format is non-paletted, which I believe is always the case.

LONG nBufferSize = 0;
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, NULL));
CHeapPtr<BITMAPINFO> pBitmapInfo;
ATLENSURE_THROW(pBitmapInfo.AllocateBytes(nBufferSize), E_OUTOFMEMORY);
ATLENSURE_SUCCEEDED(pBasicVideo->GetCurrentImage(&nBufferSize, (LONG*) (BITMAPINFO*) pBitmapInfo));
const BYTE* pnData = (const BYTE*) (&pBitmapInfo->bmiHeader + 1);
// NOTE: You might wish to handle <=8 bpp bitmaps here
ATLASSERT(pBitmapInfo->bmiHeader.biBitCount > 8);
ATLASSERT(pBitmapInfo->bmiHeader.biCompression == BI_RGB);
ATLASSERT(pBitmapInfo->bmiHeader.biSizeImage);
BITMAPFILEHEADER BitmapFileHeader;
ZeroMemory(&BitmapFileHeader, sizeof BitmapFileHeader);
BitmapFileHeader.bfType = 'MB';
BitmapFileHeader.bfSize = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize + pBitmapInfo->bmiHeader.biSizeImage);
BitmapFileHeader.bfOffBits = (DWORD) (sizeof (BITMAPFILEHEADER) + pBitmapInfo->bmiHeader.biSize);
ATLENSURE_SUCCEEDED(File.Write(&BitmapFileHeader, sizeof BitmapFileHeader));
ATLENSURE_SUCCEEDED(File.Write(&pBitmapInfo->bmiHeader, pBitmapInfo->bmiHeader.biSize));
ATLENSURE_SUCCEEDED(File.Write(pnData, (DWORD) pBitmapInfo->bmiHeader.biSizeImage));

Leave a Reply