正在阅读:DShow中实现抓图的几种方法DShow中实现抓图的几种方法

2005-08-17 10:40 出处: 作者:dankes 责任编辑:xietaoming

  通过IBasicVideo::GetCurrentImage接口

  对于该接口,Video Renderer和Video Mixing Renderer(VMR)有不同的实现。

  A)Video Renderer

  如果该Renderer使用了DDraw加速的话,该调用会失败。在调用该接口的时候,必须首先暂停Renderer(可以通过IMediaControl::Pause()暂停,如果不能确信该操作是否成功,应该调用IMediaControl::GetState()判断状态)。

  B)Video Mixing Renderer

  对于VMR,该方法都会成功(不管是否运用了DDraw加速,也不管是否是暂停状态),此时对于它所有的状态(running, stopped, or paused)都适用。

  函数Grabber代码如下(调用该函数的时候应该先将媒体文件暂停,原因上面已经说了):

#001 bool Grabber(IBasicVideo mBasicVideo, TCHAR *szFilename)
#002 {
#003   if (mBasicVideo)
#004   {
#005       long bitmapSize = 0;
#006   if(SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize, 0)))
#007       {
#008          //if语句里面的操作时取得buffer的size。
#009          //当我们在布确定image buffer的大小的情况下,我们给
#010       //GetCurrentImage的第二个参数传递0或者NULL,取得buffer的
#011          //大小供以后使用。
#012          bool pass = false;
#013          unsigned char * buffer = new unsigned char[bitmapSize];
#014 if(SUCCEEDED(mBasicVideo->GetCurrentImage(&bitmapSize,(long*)buffer)))
#015          {
#016              //此时已经用到刚才所取得的大小(分配空间)
#017              BITMAPFILEHEADER  hdr;    //Bitmap的头信息
#018              LPBITMAPINFOHEADER   lpbi; // Bitmap的文件信息(包括数据)
#019
#020              lpbi = (LPBITMAPINFOHEADER)buffer;
#021
#022              int nColors = 1 << lpbi->biBitCount;
#023              if (nColors > 256)
#024                 nColors = 0;
#025
#026              hdr.bfType    = ((WORD) ('M' << 8) | 'B');    //always is "BM"
#027              hdr.bfSize    = bitmapSize + sizeof( hdr );
#028              hdr.bfReserved1   = 0;
#029              hdr.bfReserved2   = 0;
#030              hdr.bfOffBits     = (DWORD) (sizeof(BITMAPFILEHEADER) + lpbi->biSize
#031              CFile bitmapFile(outFile, CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
#032              bitmapFile.Write(&hdr, sizeof(BITMAPFILEHEADER));
#033              bitmapFile.Write(buffer, bitmapSize);
#034              bitmapFile.Close();
#035              pass = true;
#036          }
#037          delete [] buffer; //数据用过之后记得要释放空间
#038          return true;
#039       }
#040   }
#041  
#042   return false;
#043 }

  IMediaDet接口

  IMediaDet接口可以取得媒体文件的信息。SDK里面的示例代码(没有写入文件):

#001 long size;
#002 //取得图像帧的大小,给GetBitmapBits的第三个参数传递0 or NULL
#003 hr = pDet->GetBitmapBits(0, &size, 0, width, height);
#004 if(SUCCEEDED(hr))
#005 {
#006   char *pBuffer = new char[size];
#007   if(!pBuffer)
#008   {
#009       return E_OUTOFMEMORY;
#010   }
#011  
#012   try
#013   {
#014       hr = pDet->GetbitmapsBits(0, 0, pBuffer, width, height);
#015   }
#016   catch(...)
#017   {
#018       delete [] pBuffer;
#019       throw;
#020   }
#021  
#022   if(SUCCEEDED(hr))
#023   {
#024       BITMAPINFOHEADER *bmih = (BITMAPINFOHEADER*)pBuffer;
#025       HDC    hdcDest = GetDC(0);
#026      
#027       //Find the address of the start of the image data
#028       void *pData = pBuffer + sizeof(BITMAPINFOHEADER);
#029      
#030       //Note: In general a BITMAPINFOHEADER can include extra color
#031       //information at the end, so calculating the offset to the image
#032       //data i snot generally correct. However, the IMediaDet interface
#033       //always returns an RGB-24 image with no extra color information
#034         
#035       BITMAPINFO bmi;
#036       ZeroMemory(&bmi, sizeof(BITMAPINFO));
#037       CopyMemory(&(bmi.bmiHeader), bmih, sizeof(BITMAPINFOHEADER));
#038       HBITMAP hBitmap = CreateDIBitmap(hdcDect, bmih, CBM_INIT,
#039                     pData, &bmi, DIB_RGB_COLORS);
#040   }
#041  
#042   delete [] pBuffer;
#043 }

  该方法并没有写入bitmap,具体的写入过程可以参加上面的几种方法。

键盘也能翻页,试试“← →”键

相关文章

关注我们

最新资讯离线随时看 聊天吐槽赢奖品