Hi,
I have found this code:
// BGRA U8 Bitmap
struct Bitmap {
int Width = 0;
int Height = 0;
std::vector<uint8_t> Buf;
};
// WinDesktopDup hides the gory details of capturing the screen using the
// Windows Desktop Duplication API
class WinDesktopDup {
public:
Bitmap Latest;
int OutputNumber = 0;
~WinDesktopDup();
Error Initialize();
void Close();
bool CaptureNext();
private:
ID3D11Device* D3DDevice = nullptr;
ID3D11DeviceContext* D3DDeviceContext = nullptr;
IDXGIOutputDuplication* DeskDupl = nullptr;
DXGI_OUTPUT_DESC OutputDesc;
bool HaveFrameLock = false;
};
bool WinDesktopDup::CaptureNext()
{
if (!DeskDupl)
return false;
HRESULT hr;
// according to the docs, it's best for performance if we hang onto the frame for as long as possible,
// and only release the previous frame immediately before acquiring the next one. Something about
// the OS coalescing updates, so that it doesn't have to store them as distinct things.
if (HaveFrameLock) {
HaveFrameLock = false;
hr = DeskDupl->ReleaseFrame();
// ignore response
}
IDXGIResource* deskRes = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
hr = DeskDupl->AcquireNextFrame(0, &frameInfo, &deskRes);
if (hr == DXGI_ERROR_WAIT_TIMEOUT) {
// nothing to see here
return false;
}
if (FAILED(hr)) {
// perhaps shutdown and reinitialize
auto msg = tsf::fmt("Acquire failed: %x\n", hr);
OutputDebugStringA(msg.c_str());
return false;
}
HaveFrameLock = true;
ID3D11Texture2D* gpuTex = nullptr;
hr = deskRes->QueryInterface(__uuidof(ID3D11Texture2D), (void**) &gpuTex);
deskRes->Release();
deskRes = nullptr;
if (FAILED(hr)) {
// not expected
return false;
}
bool ok = true;
D3D11_TEXTURE2D_DESC desc;
gpuTex->GetDesc(&desc);
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GDI_COMPATIBLE ?
ID3D11Texture2D* cpuTex = nullptr;
hr = D3DDevice->CreateTexture2D(&desc, nullptr, &cpuTex);
if (SUCCEEDED(hr)) {
D3DDeviceContext->CopyResource(cpuTex, gpuTex);
} else {
// not expected
ok = false;
}
D3D11_MAPPED_SUBRESOURCE sr;
hr = D3DDeviceContext->Map(cpuTex, 0, D3D11_MAP_READ, 0, &sr);
if (SUCCEEDED(hr)) {
if (Latest.Width != desc.Width || Latest.Height != desc.Height) {
Latest.Width = desc.Width;
Latest.Height = desc.Height;
Latest.Buf.resize(desc.Width * desc.Height * 4);
}
for (int y = 0; y < (int) desc.Height; y++)
memcpy(Latest.Buf.data() + y * desc.Width * 4, (uint8_t*) sr.pData + sr.RowPitch * y, desc.Width * 4);
D3DDeviceContext->Unmap(cpuTex, 0);
} else {
ok = false;
}
cpuTex->Release();
gpuTex->Release();
return ok;
}
that get a complete bitmap buffer of a frame and after do a test I see that work.
I need to extract on "Buf" or other the RGBTRIPLE rgb of a single pixel.
In short I need a function like this or similar:
RGBTRIPLE GetPixelColor(BITMAP Buf, int X, Y)
{
RGBTRIPLE Rgb;
rgb.rgbtRed = Buf(red);
rgb.rgbtGreen = Buf(green);
rgbtBlue= Buf(Blue);
return Rgb;
}
another solution will be use CopySubresourceRegion instead CopyResource and you can copy a single pixel but I don't known how use it.
Can you help me please ?