HBITMAP DesktopCapturer::captureScreen()
{
HDC hScrDC, hMemDC; // screen DC and memory DC
int nX, nY, nX2, nY2; // coordinates of rectangle to grab
int nWidth, nHeight; // DIB width and height
int xScrn, yScrn; // screen resolution
HGDIOBJ hOldBitmap , hBitmap;
// create a DC for the screen and create
// a memory DC compatible to screen DC
hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
hMemDC = CreateCompatibleDC(hScrDC); // get points of rectangle to grab
DisplayMode desktop = Graphics().GetDesktopDisplayMode();
nX = 0;
nY = 0;
nX2 = desktop.Width;
nY2 = desktop.Height;
nWidth = nX2 - nX;
nHeight = nY2 - nY;
// create a bitmap compatible with the screen DC
hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
// select new bitmap into memory DC
hOldBitmap = SelectObject (hMemDC, hBitmap);
// bitblt screen DC to memory DC
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hScrDC, nX, nY, SRCCOPY | CAPTUREBLT);
// select old bitmap back into memory DC and get handle to
// bitmap of the screen
hBitmap = SelectObject(hMemDC, hOldBitmap);
// clean up
DeleteDC(hScrDC);
DeleteDC(hMemDC);
// return handle to the bitmap
return (HBITMAP)hBitmap;
}
bool DesktopCapturer::convertToDib(HBITMAP &hBitmap)
{
bool bConverted = false;
BITMAP stBitmap;
if (GetObject(hBitmap, sizeof(stBitmap),
&stBitmap) && !stBitmap.bmBits)
{
// that is a DFB. Now we attempt to create
// a DIB with the same sizes and pixel format.
HDC hScreen = GetDC(NULL);
if (hScreen)
{
union {
BITMAPINFO stBitmapInfo;
BYTE pReserveSpace[sizeof(BITMAPINFO)
+ 0xFF * sizeof(RGBQUAD)];
};
ZeroMemory(pReserveSpace, sizeof(pReserveSpace));
stBitmapInfo.bmiHeader.biSize = sizeof(stBitmapInfo.bmiHeader);
stBitmapInfo.bmiHeader.biWidth = stBitmap.bmWidth;
stBitmapInfo.bmiHeader.biHeight = stBitmap.bmHeight;
stBitmapInfo.bmiHeader.biPlanes = 1;
stBitmapInfo.bmiHeader.biBitCount = stBitmap.bmBitsPixel;
stBitmapInfo.bmiHeader.biCompression = BI_RGB;
if (stBitmap.bmBitsPixel <= 8)
{
stBitmapInfo.bmiHeader.biClrUsed =
1 << stBitmap.bmBitsPixel;
// This image is paletted-managed.
// Hence we have to synthesize its palette.
}
stBitmapInfo.bmiHeader.biClrImportant =
stBitmapInfo.bmiHeader.biClrUsed;
PVOID pBits;
HBITMAP hDib = CreateDIBSection(hScreen,
&stBitmapInfo, DIB_RGB_COLORS, &pBits, NULL, 0);
if (hDib)
{
// ok, we're lucky. Now we have
// to transfer the image to the DFB.
HDC hMemSrc = CreateCompatibleDC(NULL);
if (hMemSrc)
{
HGDIOBJ hOldSrc = SelectObject(hMemSrc, hBitmap);
if (hOldSrc)
{
HDC hMemDst = CreateCompatibleDC(NULL);
if (hMemDst)
{
HGDIOBJ hOldDst = SelectObject(hMemDst, hDib);
if (hOldDst)
{
if (stBitmap.bmBitsPixel <= 8)
{
// take the DFB's palette and set it to our DIB
HPALETTE hPalette =
(HPALETTE) GetCurrentObject(hMemSrc, OBJ_PAL);
if (hPalette)
{
PALETTEENTRY pPaletteEntries[0x100];
UINT nEntries = GetPaletteEntries(hPalette,
0, stBitmapInfo.bmiHeader.biClrUsed,
pPaletteEntries);
if (nEntries)
{
for (UINT nIndex = 0; nIndex < nEntries; nIndex++)
pPaletteEntries[nEntries].peFlags = 0;
SetDIBColorTable(hMemDst, 0,
nEntries, (RGBQUAD*) pPaletteEntries) == nEntries;
}
}
}
// transfer the image using BitBlt function.
// It will probably end in the
// call to driver's DrvCopyBits function.
if (BitBlt(hMemDst, 0, 0, stBitmap.bmWidth,
stBitmap.bmHeight, hMemSrc, 0, 0, SRCCOPY))
bConverted = true; // success
SelectObject(hMemDst, hOldDst);
}
DeleteDC(hMemDst);
}
SelectObject(hMemSrc, hOldSrc);
}
DeleteDC(hMemSrc);
}
if (bConverted)
{
DeleteObject(hBitmap); // it's no longer needed
hBitmap = hDib;
}
else
DeleteObject(hDib);
}
ReleaseDC(NULL, hScreen);
}
}
return bConverted;
}
void DesktopCapturer::Init()
{
gdi_bitmap = captureScreen();
convertToDib (gdi_bitmap);
GetObject (gdi_bitmap, sizeof(BITMAP), &gdi_bitmap_data);
data_size = gdi_bitmap_data.bmWidth * gdi_bitmap_data.bmHeight * 4;
// convert from BGR to RGB:
for (int i=0; i<data_size; i+=4)
{
unsigned char tmp = ((unsigned char*)gdi_bitmap_data.bmBits);
((unsigned char*)gdi_bitmap_data.bmBits) = ((unsigned char*)gdi_bitmap_data.bmBits)[i+2];
((unsigned char*)gdi_bitmap_data.bmBits)[i+2] = tmp;
}
}
What the above code does is to take a screenshot of the whole screen, convert it to DIB format, and use this DIB BITMAP for generating a texture from the bmBits field. Before creating the texture, I convert the BGRA to RGBA for use with SOIL.
The method called to capture the desktop is "Init", at the program start. After that, I use SOIL library to create an opengl texture from the bmBits member of the gdi_bitmap_data, which works excellent on my 2 Windows 7 machines. The problem comes when I run the program on Windows XP SP3, with an 9800GT. Given the fact that the texture loading happens correctly in both cases, I think it's something to do with the GDI capture code.
Here is a screenshot of the problem. You see that not all the colours are displayed. More importantly, it seems that only the icons are captured, the rest is black, as I see it.
problematic:
normal desktop:
And here is a working screenshot, from a Windows 7 system (GMA950).
That's it, I am sorry for the post length again. I hope you can help me out here.
Thank you
Capturing screen and creating an opengl texture
Hello,
for the purpose of my game, I need to capture the entire screen and generate an opengl texture out of it. Currently, I am using GDI to do the work, the code is as follows:
(sorry for the length of the code, but I think you need to see what's happening, I explain what I am doing after the code block.)
what is the depth of the different desktop resolutions? what's the depth of the opengl texture you create?
Just look at the color of the Quicktime icon. It used to be blue but in your crapped version its orange. That leads me to the assumption that you store the pixels in a different order such as ARGB written to RGBA without changing the color layout. Hence you most likely screw the alpha value and get a black color due to either OpenGL color blending settings or the mixed up pixel color is just this black color.
Make sure you read and store the RGBA color components in the necessary formats.
Make sure you read and store the RGBA color components in the necessary formats.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement