DXGI выводит пустой массив пикселей, memcpy тоже не работает

Привет, я пытаюсь объединить данный код с моим, чтобы вывести массив пикселей из изображения, но проблема в том, что 1) он выводит пустой массив 2) memcpy не работает с unique_ptr to const void * ОШИБКА Как получить доступ к данным пикселей из ID3D11Texture2D?

Честно говоря, я не понимаю, в чем может быть проблема, потому что я сделал все, как написано. Помогите пожалуйста, может я что-то пропустил.

#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;
}

person TEARLESS    schedule 29.11.2020    source источник


Ответы (1)


В вашем коде есть несколько проблем, в частности, вам нужно сопоставить вызовы AcquireFrame/ReleaseFrame и принять тот факт, что вы не обязательно получаете изображение в первом вызове. Я объяснял это ранее в DXGI API: AcquireNextFrame() никогда не получает обновленное изображение, всегда пустой вопрос.

Я отредактировал ваш код, чтобы он работал, см. ДОБАВЛЕННЫЕ и УДАЛЕННЫЕ комментарии.

    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 и увидеть, что данные есть:

введите здесь описание изображения

person Roman R.    schedule 29.11.2020
comment
Добрый день, но вы не помогли с основной проблемой, не отображает пиксели. - person TEARLESS; 30.11.2020
comment
sptr содержит допустимые значения пикселей, представляющие изображение монитора, не можете ли вы позаботиться о пикселях оттуда? - person Roman R.; 30.11.2020
comment
pix.my/o/0bdULh?1606685706 Это то, что я пытаюсь сделать, но это отображает нули, поэтому я думаю, что он не может сканировать экран. - person TEARLESS; 30.11.2020
comment
Моя ошибка, я видел, что он правильно отображает пиксели. Помогите пожалуйста настроить, как отобразить пиксель с определенных координат? - person TEARLESS; 30.11.2020
comment
Я не понимаю вопроса. Здесь, на StackOverflow, есть вопросы и ответы, у вас был пустой массив, и, надеюсь, это решено. Пожалуйста, задайте еще вопрос и объясните, как именно вы пытаетесь отобразить пиксели, что вы для этого делаете и где застреваете. - person Roman R.; 30.11.2020
comment
stackoverflow.com/questions/65065765 / - person TEARLESS; 30.11.2020
comment
stackoverflow.com/questions/65065765 / новая команда - person TEARLESS; 30.11.2020
comment
Я упомянул, что вы отвечаете за сопоставление вызовов AcquireNextFrame и ReleaseFrame. Я отредактировал код, чтобы у вас было совпадение с первым полученным изображением, чтобы убедиться, что захваченные пиксели действительны. В вашем дальнейшем редактировании вы не можете сопоставить вызовы. - person Roman R.; 30.11.2020
comment
Добрый день. Большое спасибо за помощь, но у меня новая проблема. Я рассчитываю на вас.)) сканирует пиксели со скоростью 10 кадров в секунду и использует больше памяти"> stackoverflow.com/questions/65066779/ - person TEARLESS; 30.11.2020