创建从glReadPixels

问题描述:

我需要创建一个由glReadPixels返回的数据HBITMAP)一个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?!?!

+0

我的GDI32技能有点生疏,但你看过[CreateDIBitmap](http://msdn.microsoft.com/en-us/library/dd183491 \(v = vs.85 \).aspx)?我认为它应该只是'CreateDIBitmap(hDC,&header,CBM_INIT,pPixelData,&info,DIB_RGB_COLORS)' – user786653

+0

我已经尝试过使用CreateDIBitmap,但它不适用于我。我结束了使用BITMAPFILEHEADER和BITMAPINFOHEADER并直接写入到.bmp。如果我能够获得HBITMAP,但没有想到会更好。回到C#它是... – user907285

您是否正在使用正确的参数调用该函数。检查功能的文档:http://msdn.microsoft.com/en-us/library/dd183491(v=vs.85).aspx。看起来你已经交换了参数顺序,并且正在传递一个指向数据指针的指针。

-Timo

+0

不,那不是,甚至交换参数,只是传递指针,什么也不给我。我找到了一种获取HANDLE的方法(更新了示例),但现在不知道如何将它转换为HBITMAP – user907285

很老的线程,但我想给一个答案,至少要保持其作为一个资源库。

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);      
} 

如前所述,请注意图像被倒置。您可以交换SRCCINVERT的SRCCOPY。你也可能想确保你正在复制区域。上面的代码假定该区域与视口相匹配。