2011-08-23 85 views
0

我需要創建一個由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

回答

0

您是否正在使用正確的參數調用該函數。檢查功能的文檔:http://msdn.microsoft.com/en-us/library/dd183491(v=vs.85).aspx。看起來你已經交換了參數順序,並且正在傳遞一個指向數據指針的指針。

-Timo

+0

不,那不是,甚至交換參數,只是傳遞指針,什麼也不給我。我找到了一種獲取HANDLE的方法(更新了示例),但現在不知道如何將它轉換爲HBITMAP – user907285

0

很老的線程,但我想給一個答案,至少要保持其作爲一個資源庫。

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。你也可能想確保你正在複製區域。上面的代碼假定該區域與視口相匹配。