创建从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?!?!
答
您是否正在使用正确的参数调用该函数。检查功能的文档: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。你也可能想确保你正在复制区域。上面的代码假定该区域与视口相匹配。
我的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
我已经尝试过使用CreateDIBitmap,但它不适用于我。我结束了使用BITMAPFILEHEADER和BITMAPINFOHEADER并直接写入到.bmp。如果我能够获得HBITMAP,但没有想到会更好。回到C#它是... – user907285