如何从 ID3D11Texture2D 访问像素数据?
How to access pixels data from ID3D11Texture2D?
我正在使用 Windows 桌面复制 API 制作我自己的镜像协议。
我有这段代码:
// Get new frame
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
*Timeout = true;
return DUPL_RETURN_SUCCESS;
}
这是 FrameInfo
结构:
`typedef struct _FRAME_DATA {
ID3D11Texture2D* Frame;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
_Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData;
UINT DirtyCount;
UINT MoveCount;
} FRAME_DATA;`
我想从 ID3D11Texture2D* Frame;
中提取像素缓冲区
如何提取 BYTE *
或 unsigned char *
并获得 RGB 序列?
谢谢!
您需要使用 ID3D11Device::CreateTexture2D
创建具有 CPU 读取访问权限的第二个相同大小的纹理,使用 ID3D11DeviceContext::CopyResource
将整个帧或仅更新的部分复制到 GPU 上的此纹理或ID3D11DeviceContext::CopySubresourceRegion
(可以使用 IDXGIOutputDuplication::GetFrameDirtyRects
和 IDXGIOutputDuplication::GetFrameMoveRects
检索哪些部分已更新),映射第二个纹理以使其可由 CPU 使用 ID3D11DeviceContext::Map
访问,这给出您 D3D11_MAPPED_SUBRESOURCE
结构包含指向带有帧数据的缓冲区的指针及其大小,这就是您要查找的内容。
Microsoft 提供了一个 rather detailed Desktop Duplication API usage sample 实现上述所有步骤。
还有一个straight sample demonstrating how to save ID3D11Texture2D data to file.
您好,这是满足您要求的代码。输出将在 UCHAR
缓冲区 g_iMageBuffer
//Variable Declaration
IDXGIOutputDuplication* IDeskDupl;
IDXGIResource* lDesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO IFrameInfo;
ID3D11Texture2D* IAcquiredDesktopImage;
ID3D11Texture2D* lDestImage;
ID3D11DeviceContext* lImmediateContext;
UCHAR* g_iMageBuffer=nullptr;
//Screen capture start here
hr = lDeskDupl->AcquireNextFrame(20, &lFrameInfo, &lDesktopResource);
// >QueryInterface for ID3D11Texture2D
hr = lDesktopResource->QueryInterface(IID_PPV_ARGS(&lAcquiredDesktopImage));
lDesktopResource.Release();
// Copy image into GDI drawing texture
lImmediateContext->CopyResource(lDestImage,lAcquiredDesktopImage);
lAcquiredDesktopImage.Release();
lDeskDupl->ReleaseFrame();
// Copy GPU Resource to CPU
D3D11_TEXTURE2D_DESC desc;
lDestImage->GetDesc(&desc);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
lImmediateContext->Map(lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
std::unique_ptr<BYTE> pBuf(new BYTE[resource.RowPitch*desc.Height]);
UINT lBmpRowPitch = lOutputDuplDesc.ModeDesc.Width * 4;
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptr = pBuf.get() + resource.RowPitch*desc.Height - lBmpRowPitch;
UINT lRowPitch = std::min<UINT>(lBmpRowPitch, resource.RowPitch);
for (size_t h = 0; h < lOutputDuplDesc.ModeDesc.Height; ++h)
{
memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr -= lBmpRowPitch;
}
lImmediateContext->Unmap(lDestImage, subresource);
long g_captureSize=lRowPitch*desc.Height;
g_iMageBuffer= new UCHAR[g_captureSize];
g_iMageBuffer = (UCHAR*)malloc(g_captureSize);
//Copying to UCHAR buffer
memcpy(g_iMageBuffer,pBuf,g_captureSize);
我正在使用 Windows 桌面复制 API 制作我自己的镜像协议。 我有这段代码:
// Get new frame
HRESULT hr = m_DeskDupl->AcquireNextFrame(500, &FrameInfo, &DesktopResource);
if (hr == DXGI_ERROR_WAIT_TIMEOUT)
{
*Timeout = true;
return DUPL_RETURN_SUCCESS;
}
这是 FrameInfo
结构:
`typedef struct _FRAME_DATA {
ID3D11Texture2D* Frame;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
_Field_size_bytes_((MoveCount * sizeof(DXGI_OUTDUPL_MOVE_RECT)) + (DirtyCount * sizeof(RECT))) BYTE* MetaData;
UINT DirtyCount;
UINT MoveCount;
} FRAME_DATA;`
我想从 ID3D11Texture2D* Frame;
中提取像素缓冲区
如何提取 BYTE *
或 unsigned char *
并获得 RGB 序列?
谢谢!
您需要使用 ID3D11Device::CreateTexture2D
创建具有 CPU 读取访问权限的第二个相同大小的纹理,使用 ID3D11DeviceContext::CopyResource
将整个帧或仅更新的部分复制到 GPU 上的此纹理或ID3D11DeviceContext::CopySubresourceRegion
(可以使用 IDXGIOutputDuplication::GetFrameDirtyRects
和 IDXGIOutputDuplication::GetFrameMoveRects
检索哪些部分已更新),映射第二个纹理以使其可由 CPU 使用 ID3D11DeviceContext::Map
访问,这给出您 D3D11_MAPPED_SUBRESOURCE
结构包含指向带有帧数据的缓冲区的指针及其大小,这就是您要查找的内容。
Microsoft 提供了一个 rather detailed Desktop Duplication API usage sample 实现上述所有步骤。
还有一个straight sample demonstrating how to save ID3D11Texture2D data to file.
您好,这是满足您要求的代码。输出将在 UCHAR
缓冲区 g_iMageBuffer
//Variable Declaration
IDXGIOutputDuplication* IDeskDupl;
IDXGIResource* lDesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO IFrameInfo;
ID3D11Texture2D* IAcquiredDesktopImage;
ID3D11Texture2D* lDestImage;
ID3D11DeviceContext* lImmediateContext;
UCHAR* g_iMageBuffer=nullptr;
//Screen capture start here
hr = lDeskDupl->AcquireNextFrame(20, &lFrameInfo, &lDesktopResource);
// >QueryInterface for ID3D11Texture2D
hr = lDesktopResource->QueryInterface(IID_PPV_ARGS(&lAcquiredDesktopImage));
lDesktopResource.Release();
// Copy image into GDI drawing texture
lImmediateContext->CopyResource(lDestImage,lAcquiredDesktopImage);
lAcquiredDesktopImage.Release();
lDeskDupl->ReleaseFrame();
// Copy GPU Resource to CPU
D3D11_TEXTURE2D_DESC desc;
lDestImage->GetDesc(&desc);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
lImmediateContext->Map(lDestImage, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
std::unique_ptr<BYTE> pBuf(new BYTE[resource.RowPitch*desc.Height]);
UINT lBmpRowPitch = lOutputDuplDesc.ModeDesc.Width * 4;
BYTE* sptr = reinterpret_cast<BYTE*>(resource.pData);
BYTE* dptr = pBuf.get() + resource.RowPitch*desc.Height - lBmpRowPitch;
UINT lRowPitch = std::min<UINT>(lBmpRowPitch, resource.RowPitch);
for (size_t h = 0; h < lOutputDuplDesc.ModeDesc.Height; ++h)
{
memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr -= lBmpRowPitch;
}
lImmediateContext->Unmap(lDestImage, subresource);
long g_captureSize=lRowPitch*desc.Height;
g_iMageBuffer= new UCHAR[g_captureSize];
g_iMageBuffer = (UCHAR*)malloc(g_captureSize);
//Copying to UCHAR buffer
memcpy(g_iMageBuffer,pBuf,g_captureSize);