I am building an application that needs to capture the current screen, perform pixel-wise analysis of the captured data, and ideally draw a modified version of the data back onto the screen. Currently I have successfully found a way to capture pixel data from the screen and store it in memory using DirectX 9 and accessing the front buffer. I am not necessarily married to DirectX 9, however it has the advantage of being already installed on the target audience's computers.
// Requires the D3D9 device to be initialized.
void grabScreen(const int WIDTH, const int HEIGHT, BYTE* pBits){
d3ddev->CreateOffscreenPlainSurface(WIDTH, HEIGHT,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
d3ddev->GetFrontBufferData(0, pSurface);
//D3DXSaveSurfaceToFile(L"Desktop.jpg", D3DXIFF_JPG, pSurface, NULL, NULL);
D3DLOCKED_RECT lockedRect;
pSurface->LockRect(&lockedRect, NULL,
D3DLOCK_NO_DIRTY_UPDATE |
D3DLOCK_NOSYSLOCK | D3DLOCK_READONLY);
for (int i = 0; i < HEIGHT; i++)
{
memcpy((BYTE*)pBits + i * WIDTH * 32 / 8,
(BYTE*)lockedRect.pBits + i * lockedRect.Pitch,
WIDTH * 32 / 8);
}
pSurface->UnlockRect();
}
Next I pass *pBits through my analysis and modification routines to get what I would like to then be drawn back to the screen in some capacity. I am not looking to replace the screen necessarily, and am in fact operating on a subset of the actual screen. I have been looking all over the internet for a way to draw this pixel map back to the screen, however I cannot find a way. In the past, I have used a Pixel Buffer Object in OpenGL to achieve a similar result, but cannot find a way to do it in DirectX.
My initial thought was to put it back into a surface and then render that surface:
bool ScreenManager::generateSurface(BYTE *pData, UINT width, UINT height, IDirect3DSurface9* pSurface){
LPDIRECT3DDEVICE9 d3ddev = *this->device;
d3ddev->CreateOffscreenPlainSurface(width, height,
D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
D3DLOCKED_RECT lockedRect;
pSurface->LockRect(&lockedRect, NULL,
D3DLOCK_NOSYSLOCK);
int bytesPerPixel = pixelSize / 8;
for (int i = 0; i < height; i++)
{
memcpy(
(BYTE*)lockedRect.pBits + i * lockedRect.Pitch,
(BYTE*)pData + i * width * bytesPerPixel,
width * bytesPerPixel);
}
pSurface->UnlockRect();
return true;
}
But, I cannot find a way to directly render a surface. I think I am probably missing some fundamental understanding of how DirectX works, and I apologize for my ignorance.Any and all help would be greatly appreciated!
Thanks,
Kelly