DXGI 输出空像素数组,memcpy 也不起作用
DXGI outputs empty pixel array, memcpy also doesn't work
嗨,我正在尝试将给定的代码与我的代码结合起来,以从图像中输出一个像素数组,但问题是 1) 它输出一个空数组 2) memcpy 失败并显示“unique_ptr to const无效 * 错误”
老实说,我不明白可能是什么问题,因为我按照它说的做了一切。请帮忙,也许我错过了什么。
#include "D3D9.h"
#include <Wincodec.h>
#include <chrono>
#include <shellapi.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <Atlbase.h>
#include <comdef.h>
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <memory>
#include <algorithm>
#include <string>
#include <iostream>
#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "D3d9.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "gdi32.lib")
//using namespace System;
#define EXIT(hr) { if (FAILED(hr)) \
{std::cout<<"ERROR"<<std::endl; return -1; } }
HBITMAP GetPix(ID3D11Texture2D* d3dtex, ID3D11Device* pDevice)
{
HRESULT hr;
HBITMAP hBitmapTexture = NULL;
HGDIOBJ hBitmap;
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D* pNewTexture = NULL;
D3D11_TEXTURE2D_DESC description;
d3dtex->GetDesc(&desc);
d3dtex->GetDesc(&description);
description.BindFlags = 0;
description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
description.Usage = D3D11_USAGE_STAGING;
description.MiscFlags = 0;
if (FAILED(pDevice->CreateTexture2D(&description, NULL, &pNewTexture)))
{
return NULL;
}
ID3D11DeviceContext* ctx = NULL;
pDevice->GetImmediateContext(&ctx);
ctx->CopyResource(pNewTexture, d3dtex);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
ctx->Map(pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
// Copy from texture to bitmap buffer.
std::unique_ptr<BYTE> pBuf(new BYTE[resource.RowPitch * desc.Height]);
UINT lBmpRowPitch = desc.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 < desc.Height; ++h)
{
memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr -= lBmpRowPitch;
}
ctx->Unmap(pNewTexture, subresource);
long g_captureSize = lRowPitch * desc.Height;
UCHAR* g_iMageBuffer = nullptr;
g_iMageBuffer = new UCHAR[g_captureSize];
g_iMageBuffer = (UCHAR*)malloc(g_captureSize);
//Copying to UCHAR buffer
//memcpy(g_iMageBuffer, pBuf, g_captureSize);
std::cout << pBuf<< std::endl;
}
int main()
{
HRESULT hr;
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
D3D_FEATURE_LEVEL d3dFeatLvl;
ID3D11Device* pDevice = nullptr;
ID3D11DeviceContext* pImmediateContext = nullptr;
hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE,
NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&pDevice,
&d3dFeatLvl,
&pImmediateContext);
EXIT(hr);
IDXGIDevice* DxgiDevice = nullptr;
hr = pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice));
IDXGIAdapter* DxgiAdapter = nullptr;
hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter));
EXIT(hr);
DxgiDevice->Release();
DxgiDevice = nullptr;
IDXGIOutput* DxgiOutput = nullptr;
hr = DxgiAdapter->EnumOutputs(0, &DxgiOutput);
EXIT(hr);
DxgiAdapter->Release();
DxgiAdapter = nullptr;
DXGI_OUTPUT_DESC OutputDesc;
DxgiOutput->GetDesc(&OutputDesc);
IDXGIOutput1* DxgiOutput1 = nullptr;
hr = DxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&DxgiOutput1));
EXIT(hr);
DxgiOutput->Release();
DxgiOutput = nullptr;
IDXGIOutputDuplication* DeskDupl = nullptr;
hr = DxgiOutput1->DuplicateOutput(pDevice, &DeskDupl);
EXIT(hr);
DxgiOutput1->Release();
DxgiOutput1 = nullptr;
DXGI_OUTDUPL_DESC OutputDuplDesc;
DeskDupl->GetDesc(&OutputDuplDesc);
ID3D11Texture2D* AcquiredDesktopImage = nullptr;
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
hr = DeskDupl->AcquireNextFrame(20, &FrameInfo, &DesktopResource);
EXIT(hr);
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&AcquiredDesktopImage));
EXIT(hr);
DesktopResource->Release();
DesktopResource = nullptr;
GetPix(AcquiredDesktopImage, pDevice);
//GETRGB(AcquiredDesktopImage, pDevice);
return 0;
}
您的代码中存在一些问题,具体而言,您需要匹配 AcquireFrame
/ReleaseFrame
调用并接受您不一定在第一次调用中获取图片的事实。我之前在 DXGI API: AcquireNextFrame() never grabs an updated image, always blank 问题中对此进行了解释。
我编辑了您的代码以使其工作,请参阅添加和删除的评论。
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
// <<--- BEGIN ADDED
for(; ; )
{
hr = DeskDupl->AcquireNextFrame(20, &FrameInfo, &DesktopResource);
EXIT(hr);
if(FrameInfo.LastPresentTime.QuadPart == 0)
{
DesktopResource->Release();
hr = DeskDupl->ReleaseFrame();
EXIT(hr);
continue;
}
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&AcquiredDesktopImage));
GetPix(AcquiredDesktopImage, pDevice);
break;
}
// <<--- END ADDED
EXIT(hr);
DesktopResource->Release();
DesktopResource = nullptr;
//GetPix(AcquiredDesktopImage, pDevice); // <<--- REMOVED
//GETRGB(AcquiredDesktopImage, pDevice);
你可以在 sptr
行后设置一个断点,然后查看那里的数据:
嗨,我正在尝试将给定的代码与我的代码结合起来,以从图像中输出一个像素数组,但问题是 1) 它输出一个空数组 2) memcpy 失败并显示“unique_ptr to const无效 * 错误”
老实说,我不明白可能是什么问题,因为我按照它说的做了一切。请帮忙,也许我错过了什么。
#include "D3D9.h"
#include <Wincodec.h>
#include <chrono>
#include <shellapi.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <Atlbase.h>
#include <comdef.h>
#include <windows.h>
#include <shlobj.h>
#include <shellapi.h>
#include <dxgi1_2.h>
#include <d3d11.h>
#include <memory>
#include <algorithm>
#include <string>
#include <iostream>
#pragma comment(lib, "D3D11.lib")
#pragma comment(lib, "D3d9.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "gdi32.lib")
//using namespace System;
#define EXIT(hr) { if (FAILED(hr)) \
{std::cout<<"ERROR"<<std::endl; return -1; } }
HBITMAP GetPix(ID3D11Texture2D* d3dtex, ID3D11Device* pDevice)
{
HRESULT hr;
HBITMAP hBitmapTexture = NULL;
HGDIOBJ hBitmap;
D3D11_TEXTURE2D_DESC desc;
ID3D11Texture2D* pNewTexture = NULL;
D3D11_TEXTURE2D_DESC description;
d3dtex->GetDesc(&desc);
d3dtex->GetDesc(&description);
description.BindFlags = 0;
description.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
description.Usage = D3D11_USAGE_STAGING;
description.MiscFlags = 0;
if (FAILED(pDevice->CreateTexture2D(&description, NULL, &pNewTexture)))
{
return NULL;
}
ID3D11DeviceContext* ctx = NULL;
pDevice->GetImmediateContext(&ctx);
ctx->CopyResource(pNewTexture, d3dtex);
D3D11_MAPPED_SUBRESOURCE resource;
UINT subresource = D3D11CalcSubresource(0, 0, 0);
ctx->Map(pNewTexture, subresource, D3D11_MAP_READ_WRITE, 0, &resource);
// Copy from texture to bitmap buffer.
std::unique_ptr<BYTE> pBuf(new BYTE[resource.RowPitch * desc.Height]);
UINT lBmpRowPitch = desc.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 < desc.Height; ++h)
{
memcpy_s(dptr, lBmpRowPitch, sptr, lRowPitch);
sptr += resource.RowPitch;
dptr -= lBmpRowPitch;
}
ctx->Unmap(pNewTexture, subresource);
long g_captureSize = lRowPitch * desc.Height;
UCHAR* g_iMageBuffer = nullptr;
g_iMageBuffer = new UCHAR[g_captureSize];
g_iMageBuffer = (UCHAR*)malloc(g_captureSize);
//Copying to UCHAR buffer
//memcpy(g_iMageBuffer, pBuf, g_captureSize);
std::cout << pBuf<< std::endl;
}
int main()
{
HRESULT hr;
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
D3D_FEATURE_LEVEL d3dFeatLvl;
ID3D11Device* pDevice = nullptr;
ID3D11DeviceContext* pImmediateContext = nullptr;
hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE,
NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevels,
ARRAYSIZE(featureLevels),
D3D11_SDK_VERSION,
&pDevice,
&d3dFeatLvl,
&pImmediateContext);
EXIT(hr);
IDXGIDevice* DxgiDevice = nullptr;
hr = pDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&DxgiDevice));
IDXGIAdapter* DxgiAdapter = nullptr;
hr = DxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&DxgiAdapter));
EXIT(hr);
DxgiDevice->Release();
DxgiDevice = nullptr;
IDXGIOutput* DxgiOutput = nullptr;
hr = DxgiAdapter->EnumOutputs(0, &DxgiOutput);
EXIT(hr);
DxgiAdapter->Release();
DxgiAdapter = nullptr;
DXGI_OUTPUT_DESC OutputDesc;
DxgiOutput->GetDesc(&OutputDesc);
IDXGIOutput1* DxgiOutput1 = nullptr;
hr = DxgiOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&DxgiOutput1));
EXIT(hr);
DxgiOutput->Release();
DxgiOutput = nullptr;
IDXGIOutputDuplication* DeskDupl = nullptr;
hr = DxgiOutput1->DuplicateOutput(pDevice, &DeskDupl);
EXIT(hr);
DxgiOutput1->Release();
DxgiOutput1 = nullptr;
DXGI_OUTDUPL_DESC OutputDuplDesc;
DeskDupl->GetDesc(&OutputDuplDesc);
ID3D11Texture2D* AcquiredDesktopImage = nullptr;
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
hr = DeskDupl->AcquireNextFrame(20, &FrameInfo, &DesktopResource);
EXIT(hr);
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&AcquiredDesktopImage));
EXIT(hr);
DesktopResource->Release();
DesktopResource = nullptr;
GetPix(AcquiredDesktopImage, pDevice);
//GETRGB(AcquiredDesktopImage, pDevice);
return 0;
}
您的代码中存在一些问题,具体而言,您需要匹配 AcquireFrame
/ReleaseFrame
调用并接受您不一定在第一次调用中获取图片的事实。我之前在 DXGI API: AcquireNextFrame() never grabs an updated image, always blank 问题中对此进行了解释。
我编辑了您的代码以使其工作,请参阅添加和删除的评论。
IDXGIResource* DesktopResource = nullptr;
DXGI_OUTDUPL_FRAME_INFO FrameInfo;
// <<--- BEGIN ADDED
for(; ; )
{
hr = DeskDupl->AcquireNextFrame(20, &FrameInfo, &DesktopResource);
EXIT(hr);
if(FrameInfo.LastPresentTime.QuadPart == 0)
{
DesktopResource->Release();
hr = DeskDupl->ReleaseFrame();
EXIT(hr);
continue;
}
hr = DesktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&AcquiredDesktopImage));
GetPix(AcquiredDesktopImage, pDevice);
break;
}
// <<--- END ADDED
EXIT(hr);
DesktopResource->Release();
DesktopResource = nullptr;
//GetPix(AcquiredDesktopImage, pDevice); // <<--- REMOVED
//GETRGB(AcquiredDesktopImage, pDevice);
你可以在 sptr
行后设置一个断点,然后查看那里的数据: