ID3D11DeviceContext渲染后的数据存储为BMP图片
2024-07-04
8
0
void SaveBackBufferToFile(IDXGISwapChain1* pSwapChain, ID3D11Device* pDevice, ID3D11DeviceContext* pDeviceContext) {
// 获取当前的渲染目标图像
ID3D11Texture2D* pBackBuffer = nullptr;
HRESULT hr = pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&pBackBuffer);
if (FAILED(hr))
{
// 错误处理
return;
}
// 创建一个可用于读取的纹理
D3D11_TEXTURE2D_DESC desc;
pBackBuffer->GetDesc(&desc);
D3D11_TEXTURE2D_DESC copyDesc = desc;
copyDesc.Usage = D3D11_USAGE_STAGING;
copyDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
copyDesc.BindFlags = 0;
D3D11_SUBRESOURCE_DATA subdata;
RtlZeroMemory(&subdata, sizeof(D3D11_SUBRESOURCE_DATA));
subdata.pSysMem = malloc(1280 * 720 * 4);
ID3D11Texture2D* pStagingTexture = nullptr;
hr = pDevice->CreateTexture2D(©Desc, NULL, &pStagingTexture);
if (FAILED(hr))
{
// 错误处理
pBackBuffer->Release();
return;
}
// 复制图像数据到目标纹理
pDeviceContext->CopyResource(pStagingTexture, pBackBuffer);
// 读取图像数据到 CPU 内存
D3D11_MAPPED_SUBRESOURCE mappedResource;
hr = pDeviceContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedResource);
if (FAILED(hr)) {
// 错误处理
pStagingTexture->Release();
pBackBuffer->Release();
return;
}
// BMP 文件头和信息头
BITMAPFILEHEADER bfh;
BITMAPINFOHEADER bih;
ZeroMemory(&bfh, sizeof(bfh));
ZeroMemory(&bih, sizeof(bih));
bfh.bfType = 0x4D42; // "BM"
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
bfh.bfSize = bfh.bfOffBits + desc.Width * desc.Height * 4;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biWidth = desc.Width;
bih.biHeight = desc.Height; // BMP 文件中的高度是负值表示从顶部到底部扫描
bih.biPlanes = 1;
bih.biBitCount = 32; // 32位颜色深度
bih.biCompression = BI_RGB;
// 打开文件进行写入
FILE* pFile = fopen("screenshot.bmp", "wb");
if (pFile) {
fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, pFile);
fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, pFile);
fwrite(mappedResource.pData, desc.Width * desc.Height * 4, 1, pFile);
fclose(pFile);
}
pDeviceContext->Unmap(pStagingTexture, 0);
pStagingTexture->Release();
pBackBuffer->Release();
}