当前位置:   article > 正文

C++ Dxgi快速截屏并保存为rgb格式和bmp格式完整示例代码_c++ dxgi opencv

c++ dxgi opencv
  1. /**
  2. * @author wh445306
  3. * @version 1.0
  4. * @Description C++ Dxgi截屏并保存为rgb格式和bmp格式完整示例代码
  5. * @Date 2022-09-25 20:46
  6. */
  7. #include <d3d11.h>
  8. #include <dxgi1_2.h>
  9. #include <stdio.h>
  10. #pragma comment(lib, "d3d11.lib")
  11. #pragma comment(lib, "dxgi.lib")
  12. #pragma warning(disable:4996)
  13. // 将RGB格式图片转成bmp格式
  14. void RGBDataSaveAsBmpFile(
  15. const char * bmpFile, // BMP文件名称
  16. unsigned char * pRgbData, // 图像数据
  17. int width, // 图像宽度
  18. int height, // 图像高度
  19. int biBitCount, // 位图深度
  20. bool flipvertical) // 图像是否需要垂直翻转
  21. {
  22. int size = 0;
  23. int bitsPerPixel = 3;
  24. if (biBitCount == 24)
  25. {
  26. bitsPerPixel = 3;
  27. size = width * height * bitsPerPixel * sizeof(char); // 每个像素点3个字节
  28. }
  29. else if (biBitCount == 32)
  30. {
  31. bitsPerPixel = 4;
  32. size = width * height * bitsPerPixel * sizeof(char); // 每个像素点4个字节
  33. }
  34. else return;
  35. // 位图第一部分,文件信息
  36. BITMAPFILEHEADER bfh;
  37. bfh.bfType = (WORD)0x4d42; //图像格式 必须为'BM'格式
  38. bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);//真正的数据的位置
  39. bfh.bfSize = size + bfh.bfOffBits;
  40. bfh.bfReserved1 = 0;
  41. bfh.bfReserved2 = 0;
  42. BITMAPINFOHEADER bih;
  43. bih.biSize = sizeof(BITMAPINFOHEADER);
  44. bih.biWidth = width;
  45. if (flipvertical)
  46. bih.biHeight = -height;//BMP图片从最后一个点开始扫描,显示时图片是倒着的,所以用-height,这样图片就正了
  47. else
  48. bih.biHeight = height;
  49. bih.biPlanes = 1;
  50. bih.biBitCount = biBitCount;
  51. bih.biCompression = BI_RGB;
  52. bih.biSizeImage = size;
  53. bih.biXPelsPerMeter = 0;
  54. bih.biYPelsPerMeter = 0;
  55. bih.biClrUsed = 0;
  56. bih.biClrImportant = 0;
  57. FILE * fp = NULL;
  58. fopen_s(&fp, bmpFile, "wb");
  59. if (!fp)
  60. return;
  61. fwrite(&bfh, 8, 1, fp);
  62. fwrite(&bfh.bfReserved2, sizeof(bfh.bfReserved2), 1, fp);
  63. fwrite(&bfh.bfOffBits, sizeof(bfh.bfOffBits), 1, fp);
  64. fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fp);
  65. fwrite(pRgbData, size, 1, fp);
  66. fclose(fp);
  67. }
  68. int main()
  69. {
  70. HRESULT hr;
  71. // Driver types supported 支持的驱动程序类型
  72. D3D_DRIVER_TYPE DriverTypes[] =
  73. {
  74. D3D_DRIVER_TYPE_HARDWARE,
  75. D3D_DRIVER_TYPE_WARP,
  76. D3D_DRIVER_TYPE_REFERENCE,
  77. };
  78. UINT NumDriverTypes = ARRAYSIZE(DriverTypes);
  79. // Feature levels supported 支持的功能级别
  80. D3D_FEATURE_LEVEL FeatureLevels[] =
  81. {
  82. D3D_FEATURE_LEVEL_11_0,
  83. D3D_FEATURE_LEVEL_10_1,
  84. D3D_FEATURE_LEVEL_10_0,
  85. D3D_FEATURE_LEVEL_9_1
  86. };
  87. UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
  88. D3D_FEATURE_LEVEL FeatureLevel;
  89. ID3D11Device *_pDX11Dev = nullptr;
  90. ID3D11DeviceContext *_pDX11DevCtx = nullptr;
  91. // Create D3D device 创建D3D设备
  92. for (UINT index = 0; index < NumDriverTypes; index++)
  93. {
  94. hr = D3D11CreateDevice(nullptr,
  95. DriverTypes[index],
  96. nullptr, 0,
  97. FeatureLevels,
  98. NumFeatureLevels,
  99. D3D11_SDK_VERSION,
  100. &_pDX11Dev,
  101. &FeatureLevel,
  102. &_pDX11DevCtx);
  103. if (SUCCEEDED(hr)) {
  104. break;
  105. }
  106. }
  107. IDXGIDevice *_pDXGIDev = nullptr;
  108. // Get DXGI device 获取 DXGI 设备
  109. hr = _pDX11Dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&_pDXGIDev));
  110. if (FAILED(hr)) {
  111. return false;
  112. }
  113. IDXGIAdapter *_pDXGIAdapter = nullptr;
  114. // Get DXGI adapter 获取 DXGI 适配器
  115. hr = _pDXGIDev->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&_pDXGIAdapter));
  116. if (FAILED(hr)) {
  117. return false;
  118. }
  119. UINT i = 0;
  120. IDXGIOutput *_pDXGIOutput = nullptr;
  121. // Get output 获取输出
  122. hr = _pDXGIAdapter->EnumOutputs(i, &_pDXGIOutput);
  123. if (FAILED(hr)) {
  124. return false;
  125. }
  126. DXGI_OUTPUT_DESC DesktopDesc;
  127. // Get output description struct 获取输出描述结构
  128. _pDXGIOutput->GetDesc(&DesktopDesc);
  129. IDXGIOutput1 *_pDXGIOutput1 = nullptr;
  130. // QI for Output1 请求接口给Output1
  131. hr = _pDXGIOutput->QueryInterface(__uuidof(IDXGIOutput1), reinterpret_cast<void**>(&_pDXGIOutput1));
  132. if (FAILED(hr)) {
  133. return false;
  134. }
  135. IDXGIOutputDuplication *_pDXGIOutputDup = nullptr;
  136. // Create desktop duplication 创建桌面副本
  137. hr = _pDXGIOutput1->DuplicateOutput(_pDX11Dev, &_pDXGIOutputDup);
  138. if (FAILED(hr)) {
  139. return false;
  140. }
  141. for (int i = 0; i < 3; i++)
  142. {
  143. IDXGIResource *desktopResource = nullptr;
  144. DXGI_OUTDUPL_FRAME_INFO frameInfo;
  145. hr = _pDXGIOutputDup->AcquireNextFrame(20, &frameInfo, &desktopResource);
  146. if (FAILED(hr))
  147. {
  148. if (hr == DXGI_ERROR_WAIT_TIMEOUT)
  149. {
  150. if (desktopResource) {
  151. desktopResource->Release();
  152. desktopResource = nullptr;
  153. }
  154. hr = _pDXGIOutputDup->ReleaseFrame();
  155. }
  156. else
  157. {
  158. return false;
  159. }
  160. }
  161. ID3D11Texture2D *_pDX11Texture = nullptr;
  162. // query next frame staging buffer 查询下一帧暂存缓冲区
  163. hr = desktopResource->QueryInterface(__uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&_pDX11Texture));
  164. desktopResource->Release();
  165. desktopResource = nullptr;
  166. if (FAILED(hr)) {
  167. return false;
  168. }
  169. ID3D11Texture2D *_pCopyBuffer = nullptr;
  170. D3D11_TEXTURE2D_DESC desc;
  171. // copy old description 复制旧描述
  172. if (_pDX11Texture)
  173. {
  174. _pDX11Texture->GetDesc(&desc);
  175. }
  176. else if (_pCopyBuffer)
  177. {
  178. _pCopyBuffer->GetDesc(&desc);
  179. }
  180. else
  181. {
  182. return false;
  183. }
  184. // create a new staging buffer for fill frame image 为填充帧图像创建一个新的暂存缓冲区
  185. if (_pCopyBuffer == nullptr) {
  186. D3D11_TEXTURE2D_DESC CopyBufferDesc;
  187. CopyBufferDesc.Width = desc.Width;
  188. CopyBufferDesc.Height = desc.Height;
  189. CopyBufferDesc.MipLevels = 1;
  190. CopyBufferDesc.ArraySize = 1;
  191. CopyBufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
  192. CopyBufferDesc.SampleDesc.Count = 1;
  193. CopyBufferDesc.SampleDesc.Quality = 0;
  194. CopyBufferDesc.Usage = D3D11_USAGE_STAGING;
  195. CopyBufferDesc.BindFlags = 0;
  196. CopyBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  197. CopyBufferDesc.MiscFlags = 0;
  198. hr = _pDX11Dev->CreateTexture2D(&CopyBufferDesc, nullptr, &_pCopyBuffer);
  199. if (FAILED(hr)) {
  200. return false;
  201. }
  202. }
  203. if (_pDX11Texture)
  204. {
  205. // copy next staging buffer to new staging buffer 将下一个暂存缓冲区复制到新的暂存缓冲区
  206. _pDX11DevCtx->CopyResource(_pCopyBuffer, _pDX11Texture);
  207. }
  208. IDXGISurface *CopySurface = nullptr;
  209. // create staging buffer for map bits 为映射位创建暂存缓冲区
  210. hr = _pCopyBuffer->QueryInterface(__uuidof(IDXGISurface), (void **)&CopySurface);
  211. if (FAILED(hr)) {
  212. return false;
  213. }
  214. DXGI_MAPPED_RECT MappedSurface;
  215. // copy bits to user space 将位复制到用户空间
  216. hr = CopySurface->Map(&MappedSurface, DXGI_MAP_READ);
  217. char picName[128] = { 0 };
  218. snprintf(picName, sizeof(picName), "Screen%d.rgb", i);
  219. FILE *p = fopen(picName, "wb");
  220. if (SUCCEEDED(hr))
  221. {
  222. for (int i = 0; i < 1080; ++i)
  223. {
  224. fwrite(MappedSurface.pBits + i * MappedSurface.Pitch, 1, MappedSurface.Pitch, p);
  225. }
  226. CopySurface->Unmap();
  227. }
  228. fclose(p);
  229. //保存为bmp格式
  230. char picNameB[128] = { 0 };
  231. snprintf(picNameB, sizeof(picNameB), "Screen%d.bmp", i);
  232. RGBDataSaveAsBmpFile(picNameB, MappedSurface.pBits, 1920, 1080, 32, true);
  233. CopySurface->Unmap();
  234. hr = CopySurface->Release();
  235. CopySurface = nullptr;
  236. if (_pDXGIOutputDup)
  237. {
  238. hr = _pDXGIOutputDup->ReleaseFrame();
  239. }
  240. //Sleep(1000);
  241. }
  242. return 0;
  243. }

效果如下:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/430054
推荐阅读
相关标签
  

闽ICP备14008679号