Создание HBITMAP из glReadPixels - PullRequest
       65

Создание HBITMAP из glReadPixels

0 голосов
/ 23 августа 2011

Мне нужно создать HBITMAP из данных, возвращаемых вызовом glReadPixels ():

HDC hCompDC = CreateCompatibleDC(NULL);
HDC hDC = GetDC();

m_hClipboardBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);

if ( m_hClipboardBitmap == NULL )
{
    throw runtime_error( "Unable to create bitmap." );
}

HBITMAP hOldBm = (HBITMAP) SelectObject( hCompDC, m_hClipboardBitmap );

int numberOfBytes = 4 * size.cx * size.cy; 
unsigned char *pPixelData = new unsigned char[numberOfBytes];

::glReadPixels(minimum.x, minimum.y, size.cx, size.cy, GL_BGRA, GL_UNSIGNED_BYTE, pPixelData);

Я попытался использовать:

BITMAPINFOHEADER header; 
header.biWidth = size.cx; 
header.biHeight = size.cy; 
header.biSizeImage = numberOfBytes; 
header.biSize = sizeof(BITMAPINFOHEADER); 
header.biPlanes = 1; 
header.biBitCount =  4 * 8; // RGBA 
header.biCompression = 0; 
header.biXPelsPerMeter = 0; 
header.biYPelsPerMeter = 0; 
header.biClrUsed = 0; 
header.biClrImportant = 0;

HANDLE handle = (HANDLE)::GlobalAlloc (GHND, sizeof(BITMAPINFOHEADER) + numberOfBytes); 

if(handle != NULL) 
{ 
    char *pData = (char *) ::GlobalLock((HGLOBAL)handle); 

    memcpy(pData,&header,sizeof(BITMAPINFOHEADER)); 
    memcpy(pData + sizeof(BITMAPINFOHEADER), pPixelData, numberOfBytes); 

    ::GlobalUnlock((HGLOBAL)handle);

    OpenClipboard(); 
    EmptyClipboard(); 
    SetClipboardData(CF_DIB, handle); 
    CloseClipboard();
}

И это вставить в mspaint OKданные хорошие) но как же я могу получить их в HBITMAP?!?!

Ответы [ 2 ]

0 голосов
/ 01 мая 2014

Очень старая ветка, но я хотел дать ответ, хотя бы сохранить его в качестве хранилища.

void WriteOpenGLPixelsToHBITMAP( HBITMAP dstHBITMAP, HDC dstDC, SIZE dims )
{

    BITMAPINFO bitmapInfo;
    {
        ::memset( &bitmapInfo, 0, sizeof( BITMAPINFO ) );
        bitmapInfo.bmiHeader.biSize        = sizeof( BITMAPINFOHEADER );
        bitmapInfo.bmiHeader.biPlanes      = 1;
        bitmapInfo.bmiHeader.biBitCount    = 32;
        bitmapInfo.bmiHeader.biCompression = BI_RGB;
        bitmapInfo.bmiHeader.biWidth       = dims.cx;
        bitmapInfo.bmiHeader.biHeight      = dims.cy;
        bitmapInfo.bmiHeader.biSizeImage   = dims.cx * dims.cy * 4; // Size 4, assuming RGBA from OpenGL
    }

    void    *bmBits = NULL;
    HDC     memDC   = ::CreateCompatibleDC( dstDC );
    HBITMAP memBM   = ::CreateDIBSection( NULL, &bitmapInfo, DIB_RGB_COLORS, &bmBits, NULL, 0 );


    ::glReadPixels( 0,
                    0,
                    dims.cx,
                    dims.cy,
                    GL_BGRA_EXT,
                    GL_UNSIGNED_BYTE,
                    bmBits );
    HGDIOBJ prevBitmap = ::SelectObject( memDC, memBM );
    HGDIOBJ obj        = ::SelectObject( dstDC, dstHBITMAP );

    // Remember that OpenGL origin is at bottom, left, but bitmaps are top, left
    if ( false == BitBlt( dstDC, 0 /*left*/, dims.cy /*top*/, dims.cx, dims.cy, memDC, 0, 0, SRCCOPY ) )
    {
        assert( false && "Failed to write pixels to HBitmap from OpenGL glReadPixels" );
    }

    ::SelectObject( memDC, prevBitmap );
    ::DeleteObject( memBM );
    ::DeleteDC( memDC );                    
}

Как уже упоминалось, помните, что изображение перевернуто. Вы можете поменять SRCCOPY на SRCINVERT. Также вы можете убедиться, что копируете регионы. Код выше предполагает, что регион соответствует области просмотра.

0 голосов
/ 23 августа 2011

Вы вызываете функцию с правильными параметрами.Ознакомьтесь с документацией функции: http://msdn.microsoft.com/en-us/library/dd183491(v=vs.85).aspx. Похоже, вы поменяли порядок параметров и передаете указатель на указатель на данные.

-Timo

...