#shared-memory #screen-capture #windows #winapi #memory-buffer #desktop-duplication

rusty-duplication

Capture the screen on Windows using the Desktop Duplication API in Rust, with shared memory support

10 releases (4 breaking)

0.5.0 May 28, 2023
0.4.5 May 26, 2023
0.3.0 May 16, 2023
0.2.0 May 13, 2023
0.1.0 May 13, 2023

#397 in GUI

MIT license

46KB
1K SLoC

rusty-duplication

license version docs.rs

Capture the screen on Windows using the Desktop Duplication API in Rust, with shared memory support.

Installation

cargo add rusty-duplication

Usage

use rusty_duplication::{
  capturer::model::Capturer,
  manager::Manager,
  utils::{FrameInfoExt, OutputDescExt},
};
use std::{fs::File, io::Write, thread, time::Duration};

fn main() {
  // manager will collect monitor info when created
  let manager = Manager::default().unwrap();
  // you can also refresh monitor info manually
  // manager.refresh();

  // you can get monitor info before capturing start
  // for ctx in &manager.contexts {
  //   ctx.dxgi_output_desc().unwrap();
  //   ctx.dxgi_outdupl_desc();
  // }

  // create capturer for a display
  // this will allocate memory buffer to store pixel data
  let mut capturer = manager.contexts[0].simple_capturer().unwrap();

  // you can also get monitor info from a capturer
  let dxgi_outdupl_desc = capturer.dxgi_outdupl_desc().unwrap();
  let dxgi_output_desc = capturer.dxgi_output_desc().unwrap();
  // get resolution width/height
  println!("size: {}x{}", dxgi_outdupl_desc.ModeDesc.Width, dxgi_outdupl_desc.ModeDesc.Height);
  // get position
  println!("left: {}, top: {}, right: {}, bottom: {}", dxgi_output_desc.DesktopCoordinates.left, dxgi_output_desc.DesktopCoordinates.top, dxgi_output_desc.DesktopCoordinates.right, dxgi_output_desc.DesktopCoordinates.bottom);

  // sleep for a while before capture to wait system to update the screen
  thread::sleep(Duration::from_millis(100));

  // capture desktop image and get the frame info
  // `safe_capture` will check if the buffer's size is enough
  let info = capturer.safe_capture().unwrap();

  // check if this is a new frame using the extension method `desktop_updated`
  if info.desktop_updated() {
    println!("captured!");
  }

  // write to a file
  // `buffer()` will return `&[u8]` in BGRA32 format
  let mut file = File::create("capture.bin").unwrap();
  file.write_all(capturer.buffer()).unwrap();
}

Advanced Usage

Shared Memory

You can use shared memory to share the buffer between processes.

This lib provides a SharedCapturer which will use Windows shared memory to store the buffer. Just call DuplicateContext.shared_capturer with a name.

manager.contexts[0].shared_capturer("Global\\MyFileMappingObject").unwrap();

Note: if your memory name starts with Global\\, you may need to run this in administrator mode. See the doc.

Customized Capturer

This lib provides low-level APIs like DuplicateContext, so you can write your own capturer. You can refer to SimpleCapturer's implementation.

Test

Run the tests using cargo test -- --test-threads=1 to prevent the tests from running in parallel.

Note: move your mouse during the test to make sure the mouse pointer is captured, also make sure your mouse is in the primary monitor.

Credit

This project is based on the following projects:

CHANGELOG

Dependencies

~139MB
~2M SLoC