Rust使用DX11进行截图并保存

写的比较糙,基本上是对照着C++转过来的。先放着,回头记不起来怎么用再回来看吧。

use image::{ImageBuffer, Rgba};
use windows::{core::Interface,Win32::Graphics::{Direct3D::{D3D_DRIVER_TYPE_HARDWARE, D3D_FEATURE_LEVEL},Direct3D11::{D3D11CreateDevice, ID3D11Device, ID3D11DeviceContext, ID3D11Texture2D,D3D11_CPU_ACCESS_READ, D3D11_CREATE_DEVICE_BGRA_SUPPORT,D3D11_CREATE_DEVICE_SINGLETHREADED, D3D11_MAPPED_SUBRESOURCE, D3D11_MAP_READ,D3D11_SDK_VERSION, D3D11_TEXTURE2D_DESC, D3D11_USAGE_STAGING,},Dxgi::{Common::{DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_SAMPLE_DESC},IDXGIDevice, IDXGIOutput1, IDXGIResource, IDXGIResource1, DXGI_OUTDUPL_FRAME_INFO,},},
};fn create_d3d_device() -> Result<(ID3D11Device, ID3D11DeviceContext), String> {let mut dervie: Option<ID3D11Device> = None;let mut feature_level = D3D_FEATURE_LEVEL::default();let mut context = None;let result = unsafe {D3D11CreateDevice(None,D3D_DRIVER_TYPE_HARDWARE,None,D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_SINGLETHREADED,None,D3D11_SDK_VERSION,Some(&mut dervie),Some(&mut feature_level),Some(&mut context),)};match result {Ok(()) => Ok((dervie.unwrap(), context.unwrap())),Err(err_msg) => Err(format!("Failed to create D3D11 device: {}", err_msg)),}
}fn main() {// 1. 创建 D3D11 设备let (device, context) = create_d3d_device().unwrap();let dx_device = device.cast::<IDXGIDevice>().unwrap();// 适配器let adapter = unsafe {match dx_device.GetAdapter() {Ok(adapter) => adapter,Err(err) => {println!("Failed to get adapter: {:?}", err);panic!();}}};// 输出let output = unsafe {match adapter.EnumOutputs(0) {Ok(output) => output,Err(err) => {println!("Failed to get output: {:?}", err);panic!();}}};// 输出1let output1 = output.cast::<IDXGIOutput1>().unwrap();let result = unsafe { output1.DuplicateOutput(&device) };let dupl_output = match result {Ok(dupl_output) => dupl_output,Err(err) => {println!("Failed to duplicate output: {:?}", err);panic!();}};// 获取帧信息let mut frame_info = DXGI_OUTDUPL_FRAME_INFO::default();let mut desktop_image: Option<IDXGIResource> = None;loop {let result =unsafe { dupl_output.AcquireNextFrame(500, &mut frame_info, &mut desktop_image) };if result.is_err() {println!("Failed to acquire next frame: {:?}", result.err());return;}if frame_info.LastPresentTime != 0 {break;}// 释放桌面图像unsafe { dupl_output.ReleaseFrame().unwrap() };}frame_info.LastPresentTime;if desktop_image.is_none() {panic!("desktop_image is none!")}let desktop_image = desktop_image.unwrap();let desktop_image = desktop_image.cast::<IDXGIResource1>().unwrap();let start_time = std::time::Instant::now();save_frame_to_file(&desktop_image, &device, &context).unwrap();let elapsed = start_time.elapsed();println!("Time elapsed: {:?}", elapsed);// 释放资源unsafe { dupl_output.ReleaseFrame().unwrap() };
}fn save_frame_to_file(desktop_image: &IDXGIResource1,device: &ID3D11Device,context: &ID3D11DeviceContext,
) -> Result<(), Box<dyn std::error::Error>> {let desktop_image1 = desktop_image.cast::<IDXGIResource1>()?;let desktop_texture: ID3D11Texture2D = desktop_image1.cast()?;let mut desc = D3D11_TEXTURE2D_DESC::default();unsafe { desktop_texture.GetDesc(&mut desc) };// 创建用于CPU读取的纹理desc.Usage = D3D11_USAGE_STAGING;desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ.0 as u32;desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;desc.SampleDesc = DXGI_SAMPLE_DESC {Count: 1,Quality: 0,};desc.BindFlags = 0;desc.MiscFlags = 0;desc.MipLevels = 1;desc.ArraySize = 1;let mut staging_texture = None;let result = unsafe { device.CreateTexture2D(&desc, None, Some(&mut staging_texture)) };if let Err(err) = result {println!("Failed to create staging texture: {:?}", err);return Err("Failed to create staging texture".into());}let staging_texture = match staging_texture {Some(staging_texture) => staging_texture,None => {println!("Failed to create staging texture");return Err("Failed to create staging texture".into());}};// 将桌面图像复制到CPU可访问的纹理unsafe {context.CopyResource(&staging_texture, &desktop_texture);}let mut mapped_resource: D3D11_MAPPED_SUBRESOURCE = Default::default();unsafe {context.Map(&staging_texture,0,D3D11_MAP_READ,0,Some(&mut mapped_resource),)?};// 将图像数据复制到 buffer 中let width = desc.Width as usize;let height = desc.Height as usize;let row_pitch = mapped_resource.RowPitch as usize;let data = unsafe {std::slice::from_raw_parts(mapped_resource.pData as *const u8, row_pitch * height)};// 创建 image crate 的缓冲区并保存let mut img_buffer = ImageBuffer::<Rgba<u8>, Vec<u8>>::new(desc.Width, desc.Height);for y in 0..height {for x in 0..width {let offset = y * row_pitch + x * 4;// 交换 R 和 B 通道let pixel = Rgba([data[offset + 2],data[offset + 1],data[offset],data[offset + 3],]);img_buffer.put_pixel(x as u32, y as u32, pixel);}}img_buffer.save("output.png")?;unsafe { context.Unmap(&staging_texture, 0) };Ok(())
}
[package]
edition = "2021"
name = "test_image"
version = "0.1.0"[dependencies]
image = "0.25.5"[dependencies.windows]
features = ["Win32_UI_WindowsAndMessaging","Win32_Graphics_Gdi","Win32_Storage_Xps","Win32_Graphics_Direct3D","Win32_Graphics_Direct3D11","Win32_Graphics_Dxgi","Win32_Graphics_Dxgi_Common","Win32_Graphics_Imaging",
]
version = "0.59.0"

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/468466.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv11实战宠物狗分类

本文采用YOLOv11作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv11以其高效的特征提取能力&#xff0c;在多个图像分类任务中展现出卓越性能。本研究针对5种宠物狗数据集进行训练和优化&#xff0c;该数据集包含丰富的宠物狗图像样本…

电信网关配置管理系统 upload_channels.php 文件上传致RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

Halcon LED灯带检测分享

目录 原图 检出图 示例代码 函数说明 代码 原图 检出图 示例代码 函数说明 LEDSensitivity : 0.6 LEDMinSize : 35 LEDMaxSize : 400 LEDMethod : 1 LEDType :1 LED (Image, LEDDefectTrans, LEDSensitivity, LEDMethod, LEDType, LEDMinSize, LEDMaxSize, R, G, B,…

Pytest-Bdd-Playwright 系列教程(7):使用测试代码生成辅助工具

Pytest-Bdd-Playwright 系列教程&#xff08;7&#xff09;&#xff1a;测试代码生成辅助工具的使用 前言一、代码生成辅助工具的设计思路1.1 功能概览1.2 适用人群 二、如何使用 pytest-bdd 代码生成器三、代码生成器的实际应用场景3.1 初学者的学习和实践3.2 大规模功能测试3…

【每日刷题】Day152

【每日刷题】Day152 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 176. 判断是否为平衡二叉树 - 力扣&#xff08;LeetCode&#xff09; 2. 最大子矩阵_牛客题霸…

【Linux】vmlinux、vmlinuz、zImage、bzImage 的区别

vmlinux vmlinux 是静态链接的可执行文件&#xff0c;但是无法直接加载启动&#xff0c;并且是非压缩的。 zImage and bzImage zImage 和 bzImage 都是 linux 的镜像&#xff08;image &#xff09;&#xff0c;前者用于老系统&#xff0c;后者用于新系统&#xff0c;都采用了…

MaxK B:基于 LLM 大语言模型的知识库问答系统!

推荐一个基于大模型的企业级知识库问答系统&#xff0c;支持管理企业知识库、对话问答、RAG 等功能。 企业知识管理的智能化革新在数字化时代&#xff0c;知识管理对于企业的重要性不言而喻。 MaxK B是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;正是为了解决这一挑…

Spring Boot 集成JWT实现Token验证详解

文章目录 Spring Boot 集成JWT实现Token验证详解一、引言二、JWT和Token基础1、什么是Token2、什么是JWT3、JWT的结构4、JWT的工作原理 三、集成JWT1、引入JWT依赖2、创建Token工具类3、创建拦截器4、注册拦截器 四、总结 Spring Boot 集成JWT实现Token验证详解 一、引言 在现…

前端CSS3 渐变详解

文章目录 CSS3 渐变详解一、引言二、CSS3 渐变基础1、线性渐变1.1、基本线性渐变1.2、改变渐变方向 2、径向渐变2.1、基本径向渐变2.2、设置径向渐变的中心 三、高级渐变技巧1、重复渐变1.1、重复线性渐变1.2、重复径向渐变 四、总结 CSS3 渐变详解 一、引言 在现代网页设计中…

openpyxl处理Excel模板,带格式拷贝行和数据填入

本文中用openpyxl操作Excell 模板,进行行拷贝和数据填充. 主要涉及单元格格式的拷贝,合并单元格的拷贝,行高和列宽的处理. 将模板表格分为三部分,头部,中间循环填充部分,尾部.模板参数中设置头部高度,循环部分高度,剩余为尾部. 拷贝时先拷贝填充头部 ,然后根据数据循环拷贝填…

IEEE 1588:电信网络的精确时间协议 (PTP)

IEEE 1588&#xff1a;电信网络的精确时间协议 IEEE 1588 PTP 概述PTP 协议特征同步类型IEEE 1588 PTP 角色IEEE 1588 PTP 的工作原理PTP 设备类型PTP 消息类型事件消息一般信息 PTP 时钟类规范PTP 配置文件 https://www.techplayon.com/ieee-1588-precision-time-protocol-ptp…

DataFrame

目录 一、创建DataFrame二、Sql语法三、DSL语法四、RDD与DataFrame互相转换 一、创建DataFrame 在SparkSql中SparkSession是创建DataFrame和执行Sql的入口&#xff0c;创建DataFrame有三种方式&#xff1a; 通过Spark的数据源进行创建 从一个存在的RDD进行转换 从Hive Tabl…

Redis 高并发分布式锁实战

目录 环境准备 一 . Redis 安装 二&#xff1a;Spring boot 项目准备 三&#xff1a;nginx 安装 四&#xff1a;Jmeter 下载和配置 案例实战 优化一&#xff1a;加 synchronized 锁 优化二&#xff1a;使用 redis 的 setnx 实现分布式锁 优化三&#xff1a;使用 Lua 脚本…

参数估计理论

估计理论的主要任务是在某种信号假设下&#xff0c;估算该信号中某个参数&#xff08;比如幅度、相位、达到时间&#xff09;的具体取值。 参数估计&#xff1a;先假定研究的问题具有某种数学模型&#xff0c; 如正态分布&#xff0c;二项分布&#xff0c;再用已知类别的学习样…

[vulnhub] DarkHole: 2

https://www.vulnhub.com/entry/darkhole-2,740/ 端口扫描主机发现 探测存活主机&#xff0c;185是靶机 # nmap -sP 192.168.75.0/24 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-11-08 18:02 CST Nmap scan report for 192.168.75.1 Host is up (0.…

【温度表达转化】

【温度表达转化】 C语言代码C代码Java代码Python代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 利用公式 C5∗(F−32)/9 &#xff08;其中C表示摄氏温度&#xff0c;F表示华氏温度&#xff09; 进行计算转化。 输出 输出一行&#x…

【Promise】JS 异步之宏队列与微队列

文章目录 1 原理图2 说明3 相关面试题3.1 面试题13.2 面试题23.3 面试题33.4 面试题4 1 原理图 2 说明 JS 中用来存储待执行回调函数的队列包含 2 个不同特定的队列&#xff1a;宏队列和微队列。宏队列&#xff1a;用来保存待执行的宏任务(回调)&#xff0c;比如&#xff1a;定…

【Linux】Linux入门实操——vim、目录结构、远程登录、重启注销

一、Linux 概述 1. 应用领域 服务器领域 linux在服务器领域是最强的&#xff0c;因为它免费、开源、稳定。 嵌入式领域 它的内核最小可以达到几百KB, 可根据需求对软件剪裁&#xff0c;近些年在嵌入式领域得到了很大的应用。 主要应用&#xff1a;机顶盒、数字电视、网络…

ubuntu下aarch64-linux-gnu(交叉编译) gdb/gdbserver(二)

ubuntu下aarch64-linux-gnu(交叉编译) gdb/gdbserver&#xff08;二&#xff09; 本教程作为gdb/gdbserver编译安装教程的一个补充&#xff0c;教会大家如何使用gdb/gdbserver进行远程调试。 如上图所示&#xff0c;我们需要将编译后的gdbserver上传至目标设备&#xff0c;其上…

Flutter错误: uses-sdk:minSdkVersion 16 cannot be smaller than version 21 declared

前言 今天要做蓝牙通信的功能&#xff0c;我使用了flutter_reactive_ble这个库&#xff0c;但是在运行的时候发现一下错误 Launching lib/main.dart on AQM AL10 in debug mode... /Users/macbook/Desktop/test/flutter/my_app/android/app/src/debug/AndroidManifest.xml Err…