RUST 利用DXGI(DirectX Graphics Infrastructure)快速截屏,保存到文件

轻松达到60帧每秒,内存和cpu占用都很低。

Cargo.toml 文件

[package]
name = "demo"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["winuser"] }
captrs="*"
shuteye="*"

main.rs 文件

use captrs::*;
use shuteye::sleep;
use std::time::Duration;
use winapi::um::wingdi::{BITMAPFILEHEADER, BITMAPINFOHEADER};

pub fn serialize_row<T: Sized>(src: &T) -> &[u8] {
    unsafe {
        ::std::slice::from_raw_parts((src as *const T) as *const u8, ::std::mem::size_of::<T>())
    }
}

fn main() {
    let mut capturer = Capturer::new(0).unwrap();

    let (w, h) = capturer.geometry();

    loop {
        let ps = capturer.capture_frame();
        if ps.is_err() {
            println!("{:?}", ps.err());
            continue;
        }
        let ps = ps.unwrap();

        let mut buf = vec![];

        // 因为图片是倒着的,要水平翻转一下
        for y in (0..h).rev() {
            for x in 0..w {
                let Bgr8 { r, g, b, a } = ps[(y * w + x) as usize];
                buf.push(b);
                buf.push(g);
                buf.push(r);
                // buf.push(a);
            }
        }

        save_to_file(
            format!("{}.bmp", 1).as_str(),
            &buf[..],
            (w) as i32,
            (h) as i32,
        );

        sleep(Duration::from_millis(1000 / 60));
    }
}

fn save_to_file(file: &str, rgba: &[u8], w: i32, h: i32) {
    let mut data: Vec<u8> = vec![];

    let bif = BITMAPFILEHEADER {
        bfType: ('B' as u16) | (('M' as u16) << 8),
        bfOffBits: 54,
        bfReserved1: 0,
        bfReserved2: 0,
        bfSize: (w * h * 3 + 54) as u32,
    };

    for v in serialize_row(&bif) {
        data.push(*v);
    }
    let bii = BITMAPINFOHEADER {
        biBitCount: 24,
        biSize: 40,
        biWidth: w,
        biHeight: h,
        biPlanes: 1,
        biCompression: 0,
        biSizeImage: (w * h * 3) as u32,
        biClrImportant: 0,
        biClrUsed: 0,
        biXPelsPerMeter: 0,
        biYPelsPerMeter: 0,
    };

    for v in serialize_row(&bii) {
        data.push(*v);
    }

    for v in rgba {
        data.push(*v);
    }

    use std::fs::File;
    use std::io::Write;

    let mut file = File::create(file).expect("create failed");
    file.write_all(&data[..]).expect("write failed");
}