none
Take a picture of the video(vga) camera in C++ RRS feed

  • Question

  • I've seen a lot of replies of how to take a picture in C#, but I would need to take this picture in C++, I'm using as a base the Skeletal Viewer provided with the SDK. At the moment I'm doing this:

     

     

    void CSkeletalViewerApp::Nui_GotVideoAlert( )
    
    {
    
        const NUI_IMAGE_FRAME * pImageFrame = NULL;
    
    	float timestamp=NULL;
    
    	char *filename=NULL;
    
    
    
        HRESULT hr = NuiImageStreamGetNextFrame(
    
            m_pVideoStreamHandle,
    
            0,
    
            &pImageFrame );
    
        if( FAILED( hr ) )
    
        {
    
            return;
    
        }
    
    
    
        NuiImageBuffer * pTexture = pImageFrame->pFrameTexture;
    
        KINECT_LOCKED_RECT LockedRect;
    
        pTexture->LockRect( 0, &LockedRect, NULL, 0 );
    
    
    
    		filename="5.bmp";
    
    
    
    	    FILE *pFile = fopen(filename, "wb");
    
    
    
    		BITMAPINFOHEADER BMIH;
    
    
    
    		BMIH.biSize = sizeof(BITMAPINFOHEADER);
    
            BMIH.biBitCount = 24;
    
            BMIH.biPlanes = 0;
    
            BMIH.biCompression = 0;
    
            BMIH.biWidth = 640;
    
            BMIH.biHeight = 480;
    
            BMIH.biSizeImage = ((((BMIH.biWidth * BMIH.biBitCount) 
    
                               + 31) & ~31) >> 3) * BMIH.biHeight;
    
    
    
            BITMAPFILEHEADER bmfh;
    
    
    
            int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize; 
    
            LONG lImageSize = BMIH.biSizeImage;
    
            LONG lFileSize = nBitsOffset + lImageSize;
    
            bmfh.bfType = 'B'+('M'<<8);
    
            bmfh.bfOffBits = nBitsOffset;
    
            bmfh.bfSize = lFileSize;
    
            bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
    
            //Write the bitmap file header
    
    
    
            UINT nWrittenFileHeaderSize = fwrite(&bmfh, 1, 
    
                         sizeof(BITMAPFILEHEADER), pFile);
    
            //And then the bitmap info header
    
    
    
            UINT nWrittenInfoHeaderSize = fwrite(&BMIH, 
    
                   1, sizeof(BITMAPINFOHEADER), pFile);
    
            //Finally, write the image data itself 
    
    
    
            //-- the data represents our drawing
    
    
    
    
    
    
    
    
    
        if( LockedRect.Pitch != 0 )
    
        {
    
            BYTE * pBuffer = (BYTE*) LockedRect.pBits;
    
    
    
            m_DrawVideo.DrawFrame( (BYTE*) pBuffer );
    
    
    
    
    
        }
    
        else
    
        {
    
            OutputDebugString( L"Buffer length of received texture is bogus\r\n" );
    
        }
    
    			UINT nWrittenDIBDataSize = 
    
    				fwrite(pImageFrame->pFrameTexture, 1,BMIH.biSizeImage, pFile);
    
    
    
        NuiImageStreamReleaseFrame( m_pVideoStreamHandle, pImageFrame );
    
    	fclose(pFile);
    
    }
    

     

    But I've got a bad image(it's in black and white and its overlapped). So any ideas?

     

    Thank you

     

    Lino

    Tuesday, October 4, 2011 1:20 PM

All replies

  • Lino,

    The data returned to you is actually 32-bits per pixel, even if only 24 of those have information. Also, you should use LockedRect.pBits to write image data, rather than pImageFrame-pFrameTexture:

    char *filename=filename="snapshot.bmp";
    FILE *pFile = NULL;
    fopen_s(&pFile, filename, "wb");
    	
    BITMAPINFOHEADER BMIH = {0};
    BMIH.biSize = sizeof(BITMAPINFOHEADER);
    BMIH.biBitCount = 32;
    BMIH.biPlanes = 1;
    BMIH.biCompression = BI_RGB;
    BMIH.biWidth = 640;
    BMIH.biHeight = 480;
    BMIH.biSizeImage = ((((BMIH.biWidth * BMIH.biBitCount) + 31) & ~31) >> 3) * BMIH.biHeight;
    
    BITMAPFILEHEADER bmfh = {0};
    int nBitsOffset = sizeof(BITMAPFILEHEADER) + BMIH.biSize; 
    LONG lImageSize = BMIH.biSizeImage;
    LONG lFileSize = nBitsOffset + lImageSize;
    bmfh.bfType = 'B'+('M'<<8);
    bmfh.bfOffBits = nBitsOffset;
    bmfh.bfSize = lFileSize;
    
    //Write the bitmap file header
    fwrite(&bmfh, 1, sizeof(BITMAPFILEHEADER), pFile);
    
    //And then the bitmap info header
    fwrite(&BMIH, 1, sizeof(BITMAPINFOHEADER), pFile);
    
    //Finally, write the image data itself
    fwrite(LockedRect.pBits, 1,BMIH.biSizeImage, pFile);
    
    fclose(pFile);
    

    Hope this helps!
    Eddy


    I'm here to help
    Friday, October 7, 2011 10:18 PM
  • i`m trying the same thing but i`m using these functions:

    void CreateBMPFile(HWND hwnd, LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC)
    {
        HANDLE hf;                  // file handle
        BITMAPFILEHEADER hdr;       // bitmap file-header
        PBITMAPINFOHEADER pbih;     // bitmap info-header
        LPBYTE lpBits;              // memory pointer
        DWORD dwTotal;              // total count of bytes
        DWORD cb;                   // incremental count of bytes
        BYTE *hp;                   // byte pointer
        DWORD dwTmp;

        pbih = (PBITMAPINFOHEADER) pbi;
        lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

        if (!lpBits)
        {
            MessageBox(hwnd,"GlobalAlloc","Error", MB_OK );
        }
    // Retrieve the color table (RGBQUAD array) and the bits
    // (array of palette indices) from the DIB.
        if (!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi,DIB_RGB_COLORS))
        {
            MessageBox(hwnd,"GetDIBits","Error",MB_OK );
        }
    // Create the .BMP file.
        hf = CreateFile(pszFile,GENERIC_READ | GENERIC_WRITE,(DWORD) 0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,(HANDLE) NULL);
        if (hf == INVALID_HANDLE_VALUE)
        {
            MessageBox( hwnd,"CreateFile","Error", MB_OK);
        }

        hdr.bfType = 0x4d42;  // File type designator "BM" 0x42 = "B" 0x4d = "M"
    // Compute the size of the entire file.
        hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage);
        hdr.bfReserved1 = 0;
        hdr.bfReserved2 = 0;
    // Compute the offset to the array of color indices.
        hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD);
    // Copy the BITMAPFILEHEADER into the .BMP file.
        if (!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp,  NULL) )
        {
            MessageBox(hwnd,"WriteFileHeader","Error",MB_OK );
        }
    // Copy the BITMAPINFOHEADER and RGBQUAD array into the file.
        if (!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, NULL))
        {
            MessageBox(hwnd,"WriteInfoHeader","Error",MB_OK );
        }
    // Copy the array of color indices into the .BMP file.
        dwTotal = cb = pbih->biSizeImage;
        hp = lpBits;
        if (!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL))
        {
            MessageBox(hwnd,"WriteFile","Error",MB_OK );
        }
    // Close the .BMP file.
        if (!CloseHandle(hf))
        {
            MessageBox(hwnd,"CloseHandle","Error",MB_OK );
        }

    // Free memory.
        GlobalFree((HGLOBAL)lpBits);
    }

    PBITMAPINFO CreateBitmapInfoStruct(HWND hwnd, HBITMAP hBmp)
    {
        BITMAP bmp;
        PBITMAPINFO pbmi;
        WORD cClrBits;
    // Retrieve the bitmap color format, width, and height.
        if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp))
        {
            MessageBox(hwnd,"GetObject","Error",MB_OK );
        }
    // Convert the color format to a count of bits.
        cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel);
        if (cClrBits == 1)
            cClrBits = 1;
        else if (cClrBits <= 4)
            cClrBits = 4;
        else if (cClrBits <= 8)
            cClrBits = 8;
        else if (cClrBits <= 16)
            cClrBits = 16;
        else if (cClrBits <= 24)
            cClrBits = 24;
        else cClrBits = 32;

    // Allocate memory for the BITMAPINFO structure. (This structure
    // contains a BITMAPINFOHEADER structure and an array of RGBQUAD
    // data structures.)

        if (cClrBits != 24)
        {
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR,sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (1<< cClrBits));
        }
    // There is no RGBQUAD array for the 24-bit-per-pixel format.
        else
            pbmi = (PBITMAPINFO) LocalAlloc(LPTR, sizeof(BITMAPINFOHEADER));

    // Initialize the fields in the BITMAPINFO structure.
        pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        pbmi->bmiHeader.biWidth = bmp.bmWidth;
        pbmi->bmiHeader.biHeight = bmp.bmHeight;
        pbmi->bmiHeader.biPlanes = bmp.bmPlanes;
        pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel;
        if (cClrBits < 24)
        {
            pbmi->bmiHeader.biClrUsed = (1<<cClrBits);
        }
    // If the bitmap is not compressed, set the BI_RGB flag.
        pbmi->bmiHeader.biCompression = BI_RGB;

    // Compute the number of bytes in the array of color
    // indices and store the result in biSizeImage.
    // For Windows NT, the width must be DWORD aligned unless
    // the bitmap is RLE compressed. This example shows this.
    // For Windows 95/98/Me, the width must be WORD aligned unless the
    // bitmap is RLE compressed.
        pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8 * pbmi->bmiHeader.biHeight;
    // Set biClrImportant to 0, indicating that all of the
    // device colors are important.
        pbmi->bmiHeader.biClrImportant = 0;

        return pbmi; //return BITMAPINFO
    }



    i use these functions :

               PBITMAPINFO pbi = CreateBitmapInfoStruct(GetDlgItem( m_hWnd, IDC_VIDEOVIEW), m_videoBMP);
               CreateBMPFile(GetDlgItem( m_hWnd, IDC_VIDEOVIEW), L"Frame.bmp", pbi, m_videoBMP, m_videoDC);

    ,where m_videoBMP, m_videoDC are similar created like m_SkeletonBMP and m_SkeletonDC.

     

    the problem is ... i save a black bitmap picture. If i use m_SkeletonBMP and m_SkeletonDC ... i save the skeletal picture sucsesfuly.

     

    I think I understand something wrong about skeletalviewer app ... it`s there another method to take a rgb frame ?

     

    Tuesday, January 10, 2012 11:50 AM