robione
December 1st, 2009, 08:17 AM
I have searched long and hard on Google and in these forums. It seems to be a common problem but I'm either something is going over my head or what I saw doesn't quite address what I'm doing. I'm using VC++ 98. I was hoping to have a "fast" app but the more I look at it, it seems I have a few wasteful steps..... that, and I'm not seeing anything resembling my screen in my app.
So what I'm doing is doing a screen capture as fast as my computer can handle it and then implementing Laplace edge detection on the color bitmap. The source is 32bit and the destination is 8bit. I'm using opengl and I'm getting like a checkerboard pattern... nothing that even resembles my screen. If I remove the laplace code and just say the color of the pixel is 128.... I should have a 2 pixel black border around that (because the mask is 5x5). That doesn't even happen.
My real concern though is actually copying the screen and accessing the color data. The rest is extra. I don't have a good understanding of the bitmap functions. What I've done is implemented what I gathered from my searches. The reason I said earlier that I think I'm wasting CPU cycles is that I think I'm copying the pixel data twice.
So the code is so long I took out some areas... wndproc.... showwindow... etc. the basic stuff.
HDC hDC;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
HDC hDesktopDC = ::GetDC(::GetDesktopWindow());
HDC hMemDC = ::CreateCompatibleDC(hDesktopDC);
int iHRes = ::GetDeviceCaps(hDesktopDC,DESKTOPHORZRES),
iVRes = ::GetDeviceCaps(hDesktopDC,DESKTOPVERTRES);
HBITMAP hBMP = CreateCompatibleBitmap(hDesktopDC,iHRes,iVRes);
MSG msg;
BYTE *bySrcData = new unsigned char[iHRes*iVRes*4],
*byDestData = new unsigned char[iHRes*iVRes*4];
BITMAPINFO bi;
BITMAPINFOHEADER bmi = {sizeof(bi.bmiHeader),iHRes,iVRes,1,24,BI_BITFIELDS,iHRes*iVRes*3,0,0,0,0};
bi.bmiHeader = bmi;
hDC = ::GetDC(hWnd);
::GetClientRect(hWnd,&r);
::SelectObject(hMemDC,hBMP);
::glViewport(0,0,r.right,r.bottom);
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
::glOrtho(0.0, r.right - 1.0, 0.0, r.bottom - 1.0, -1.0, 1.0);
::glRasterPos2i(0,0);
// Main message loop:
do {
if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::BitBlt(hMemDC,0,0,iHRes,iVRes ,hDesktopDC,0,0,SRCCOPY);
::GetDIBits(hMemDC,hBMP,0,iVRes,bySrcData,&bi,DIB_RGB_COLORS);
::memcpy(byDestData,bySrcData,iHRes*iVRes*4);
// ::Laplace(bySrcData,byDestData,iHRes,iVRes);
::glPixelZoom((double)r.right/(double)iHRes,(double)r.bottom/(double)iVRes);
::glDrawPixels(iHRes,iVRes, GL_RGBA, GL_UNSIGNED_BYTE, byDestData);
::glFlush();
::SwapBuffers(hDC);
} while( msg.message != WM_QUIT);
}
I cleaned more than I thought I would out cause just a plain memcpy yields me nothing :(
GetObject() doesn't work because the bmBits member of the BITMAP struct is NULL..... in case that crossed your mind. Thanks for the help.
(I had modified some of my code just to eliminate potential places where I would mess up... like bits/pixel and other image stuff so my last compilation was with all 32bit stuff and just a memcpy..... I have a grey window. Which means nothing is being copied over. I should see a mini version of my desktop in the window.
Might be my OGL code... switching to modelview and loading the identity after setting up the camera doesn't change any results.)
So what I'm doing is doing a screen capture as fast as my computer can handle it and then implementing Laplace edge detection on the color bitmap. The source is 32bit and the destination is 8bit. I'm using opengl and I'm getting like a checkerboard pattern... nothing that even resembles my screen. If I remove the laplace code and just say the color of the pixel is 128.... I should have a 2 pixel black border around that (because the mask is 5x5). That doesn't even happen.
My real concern though is actually copying the screen and accessing the color data. The rest is extra. I don't have a good understanding of the bitmap functions. What I've done is implemented what I gathered from my searches. The reason I said earlier that I think I'm wasting CPU cycles is that I think I'm copying the pixel data twice.
So the code is so long I took out some areas... wndproc.... showwindow... etc. the basic stuff.
HDC hDC;
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
HWND hWnd;
HDC hDesktopDC = ::GetDC(::GetDesktopWindow());
HDC hMemDC = ::CreateCompatibleDC(hDesktopDC);
int iHRes = ::GetDeviceCaps(hDesktopDC,DESKTOPHORZRES),
iVRes = ::GetDeviceCaps(hDesktopDC,DESKTOPVERTRES);
HBITMAP hBMP = CreateCompatibleBitmap(hDesktopDC,iHRes,iVRes);
MSG msg;
BYTE *bySrcData = new unsigned char[iHRes*iVRes*4],
*byDestData = new unsigned char[iHRes*iVRes*4];
BITMAPINFO bi;
BITMAPINFOHEADER bmi = {sizeof(bi.bmiHeader),iHRes,iVRes,1,24,BI_BITFIELDS,iHRes*iVRes*3,0,0,0,0};
bi.bmiHeader = bmi;
hDC = ::GetDC(hWnd);
::GetClientRect(hWnd,&r);
::SelectObject(hMemDC,hBMP);
::glViewport(0,0,r.right,r.bottom);
::glMatrixMode(GL_PROJECTION);
::glLoadIdentity();
::glOrtho(0.0, r.right - 1.0, 0.0, r.bottom - 1.0, -1.0, 1.0);
::glRasterPos2i(0,0);
// Main message loop:
do {
if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
::BitBlt(hMemDC,0,0,iHRes,iVRes ,hDesktopDC,0,0,SRCCOPY);
::GetDIBits(hMemDC,hBMP,0,iVRes,bySrcData,&bi,DIB_RGB_COLORS);
::memcpy(byDestData,bySrcData,iHRes*iVRes*4);
// ::Laplace(bySrcData,byDestData,iHRes,iVRes);
::glPixelZoom((double)r.right/(double)iHRes,(double)r.bottom/(double)iVRes);
::glDrawPixels(iHRes,iVRes, GL_RGBA, GL_UNSIGNED_BYTE, byDestData);
::glFlush();
::SwapBuffers(hDC);
} while( msg.message != WM_QUIT);
}
I cleaned more than I thought I would out cause just a plain memcpy yields me nothing :(
GetObject() doesn't work because the bmBits member of the BITMAP struct is NULL..... in case that crossed your mind. Thanks for the help.
(I had modified some of my code just to eliminate potential places where I would mess up... like bits/pixel and other image stuff so my last compilation was with all 32bit stuff and just a memcpy..... I have a grey window. Which means nothing is being copied over. I should see a mini version of my desktop in the window.
Might be my OGL code... switching to modelview and loading the identity after setting up the camera doesn't change any results.)