Re: Grab a frame from cpature device

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance

From: Andreas Pfeuti (andreas.pfeuti_at_switzerland.org)
Date: 03/19/04


Date: 18 Mar 2004 23:32:47 -0800


"The March Hare \(MVP\)" <phil@ndsm.maps> wrote in message news:<#HMA9$2CEHA.2308@tk2msftngp13.phx.gbl>...
> > Are there filters which can store a frame in a bmp-file? Or how could
> > I solve my requirement?
>
> Look at the Grabber sample and the ISampleGrabber interface in the docs.

Thanks for the hint.

I post here my code-snipets. It shows how to grabb a frame triggered
by the application and save the the frame into a bmp file.
May somebody can use it.

//first, add the Sample-Grabber-Filter to the graph
//remark m_pGrabber is a member variable containing the
ISampleGrabber-Interface

// create a sample grabber
    //
    hr = CoCreateInstance(CLSID_SampleGrabber, NULL,
CLSCTX_INPROC,IID_IBaseFilter, (void **)&pSampleGrabberFilter);
    if( FAILED(hr) )
    {
        Msg( TEXT("Could not create SampleGrabber (is qedit.dll
registered?)"));
        return hr;
    }
    pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber,
(void**)&m_pGrabber);
                if( FAILED(hr) )
    {
        Msg( TEXT("Could not get ISampleGrabber - Interface"));
        return hr;
    }

    // force it to connect to video, 24 bit
    //
    AM_MEDIA_TYPE mt;
                ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
                mt.majortype = MEDIATYPE_Video;
                mt.subtype = MEDIASUBTYPE_RGB24;
                hr = m_pGrabber->SetMediaType(&mt);
    if( FAILED( hr ) )
    {
        Msg( TEXT("Could not set media type"));
        return hr;
    }

    // add the grabber to the graph
    //
    hr = m_pGraph->AddFilter( pSampleGrabberFilter, L"Grabber" );
    if( FAILED( hr ) )
    {
        Msg( TEXT("Could not put sample grabber in graph"));
        return hr;
    }

   //set buffering mode
   hr = m_pGrabber->SetBufferSamples(TRUE);

-------------------------------------------------------------------------

//the GetStillImage - method is called by the application
//this method uses the ISampleGrabber-Interface to grabb a frame an
converts
//the frame into a MFC CBitmap - object

CBitmap* TVideoCapture::GetStillImage()
{
        // The video header contains the bitmap information.
        // Copy it into a BITMAPINFO structure.
        BITMAPINFO bitmapInfo;
        ZeroMemory(&bitmapInfo, sizeof(bitmapInfo));

        VIDEOINFOHEADER* pVih = NULL;
        pVih = this->GetVideoInfoHeader();
        if (!pVih)
        {
                return NULL;
        }

        CopyMemory(&bitmapInfo.bmiHeader, &(pVih->bmiHeader),
                                                 sizeof(BITMAPINFOHEADER));

        // Create a DIB from the bitmap header, and get a pointer to the
buffer.
        char *buffer = NULL;
        HBITMAP hBitmap = ::CreateDIBSection(0, &bitmapInfo, DIB_RGB_COLORS,
(void**)&buffer,
                                                                                                                                                         NULL, 0);

        // Copy the image into the buffer.
        long size = 0;

        //determine the required size of the buffer
        HRESULT hr = m_pGrabber->GetCurrentBuffer(&size, NULL);

        //grab the frame
        hr = m_pGrabber->GetCurrentBuffer(&size,(long *)buffer);
        if (FAILED(hr))
        {
                Msg(TEXT(TLanguageInterface::instance()->getString(EXTRACT_STILL_IMAGE_FAILED)));
                return NULL;
        }

        //make a CBitmap object and return it
        CBitmap* image = CBitmap::FromHandle(hBitmap);
        
        return image;
}

VIDEOINFOHEADER* TVideoCapture::GetVideoInfoHeader()
{
        AM_MEDIA_TYPE mt;
        HRESULT hr = m_pGrabber->GetConnectedMediaType(&mt);
        if (FAILED(hr))
        {
                        // Return error code.
        }
        // Examine the format block.
        VIDEOINFOHEADER *pVih = NULL;
        if ((mt.formattype == FORMAT_VideoInfo) &&
                        (mt.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
                        (mt.pbFormat != NULL) )
        {
                        pVih = (VIDEOINFOHEADER*)mt.pbFormat;
        }
        else
        {
                        // Wrong format. Free the format block and return an error.
                        MyFreeMediaType(mt);
                        Msg(TEXT(TLanguageInterface::instance()->getString(VIDEOINFOHEADER_WRONG_FORMAT)));
        }
        return pVih;
}

void TVideoCapture::MyFreeMediaType(AM_MEDIA_TYPE& mt)
{
    if (mt.cbFormat != 0)
    {
        CoTaskMemFree((PVOID)mt.pbFormat);
        mt.cbFormat = 0;
        mt.pbFormat = NULL;
    }
    if (mt.pUnk != NULL)
    {
        // Unecessary because pUnk should not be used, but safest.
        mt.pUnk->Release();
        mt.pUnk = NULL;
    }
}

----------------------------------------------------------------------------

//save the received CBitmap into a file
//note: m_pImage is a pointer to the CBitmap-object received by
GetStillImage()

BOOL TStillImageDialog::saveImage()
{

    BOOL success;
                
    CString fileName = "MyStillImage.bmp";
        
    HANDLE hf = CreateFile(
    fileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
    CREATE_ALWAYS, NULL, NULL );

  if( hf == INVALID_HANDLE_VALUE )
      return FALSE;

  // write out the file header
  //

  BITMAP bitmap;
  m_pImage->GetBitmap(&bitmap);

  long imageSize = bitmap.bmWidthBytes * bitmap.bmHeight;

  BITMAPFILEHEADER bfh;
  memset( &bfh, 0, sizeof( bfh ) );
  bfh.bfType = 'MB';
  bfh.bfSize = sizeof( bfh ) + imageSize + sizeof( BITMAPINFOHEADER );
  bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof(
BITMAPFILEHEADER );

  DWORD dwWritten = 0;
  success = WriteFile( hf, &bfh, sizeof( bfh ), &dwWritten, NULL );
  if (!success)
  {
     CloseHandle( hf );
     return success;
  }

  // and the bitmap format
  //
  BITMAPINFOHEADER bih;
  memset( &bih, 0, sizeof( bih ) );
  bih.biSize = sizeof( bih );
  bih.biWidth = bitmap.bmWidth;
  bih.biHeight = bitmap.bmHeight;
  bih.biPlanes = bitmap.bmPlanes;
  bih.biSizeImage = imageSize;
  bih.biBitCount = bitmap.bmBitsPixel;

  dwWritten = 0;
  success = WriteFile( hf, &bih, sizeof( bih ), &dwWritten, NULL );
  if (!success)
  {
    CloseHandle( hf );
    return success;
  }

  // and the bits themselves
  //
  dwWritten = 0;
  success = WriteFile( hf, bitmap.bmBits, imageSize, &dwWritten, NULL
);
  if (!success)
  {
    CloseHandle( hf );
    return success;
  }

  success = CloseHandle( hf );
  return success;
}

---- E N D -----------------------------------------------------------------



Relevant Pages

  • Re: Copying Bitmap
    ... Could you help me to extend the function to return a CBitmap copy of the ... bm_copy.CreateCompatibleBitmap(cdc, rsStatic.Width(), rcStatic.Height ... Add your control notification handler code here ... select a bitmap into it, and then call your OnDraw handler to write ...
    (microsoft.public.vc.mfc)
  • Re: Problem with Base64 Decoding for a CBitmap
    ... The problem is building a CBitmap from that. ... Base64 encodes 6 ... Creates an uninitilized monochrome bitmap. ... Exception is thrown here.. ...
    (microsoft.public.vc.mfc)
  • Re: Eigene Bitmaps
    ... CBitmap hält GDI Objekte und deren Handels, du kannst von CPens und soweiter ... Du sollst den Speicher der Bitmaps merken nicht die map selbst. ... Den speicher der Bitmap bekommst du zb. über GetObject ... Nun habe ich mir ein CMemoryBitmap erstellt. ...
    (microsoft.public.de.vc)
  • Re: Eigene Bitmaps
    ... CBitmap hält GDI Objekte und deren Handels, du kannst von CPens und soweiter ... Du sollst den Speicher der Bitmaps merken nicht die map selbst. ... Den speicher der Bitmap bekommst du zb. über GetObject ... Nun habe ich mir ein CMemoryBitmap erstellt. ...
    (microsoft.public.de.vc)
  • Re: Grab a frame from cpature device
    ... BOOL success; ... > BITMAP bitmap; ... > long imageSize = bitmap.bmWidthBytes * bitmap.bmHeight; ... CloseHandle(hf); ...
    (microsoft.public.win32.programmer.directx.video)