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

rusty-duplication

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

13 releases

new 0.6.1 Feb 10, 2025
0.6.0 Feb 8, 2025
0.5.0 May 28, 2023
0.4.5 May 26, 2023
0.1.0 May 13, 2023

#123 in GUI

Download history 1/week @ 2024-12-01 6/week @ 2024-12-08 1/week @ 2024-12-15 62/week @ 2025-02-02 239/week @ 2025-02-09

301 downloads per month

MIT license

36KB
764 lines

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

Basic Usage

use rusty_duplication::{FrameInfoExt, Scanner, VecCapturer};
use std::{fs::File, io::Write, thread, time::Duration};

// create a scanner to scan for monitors
let mut scanner = Scanner::new().unwrap();

// scanner implements Iterator, you can use it to iterate through monitors
let monitor = scanner.next().unwrap();

// get monitor info
monitor.dxgi_output_desc().unwrap();
monitor.dxgi_outdupl_desc();

// create a vec capturer for a monitor
// this will allocate memory buffer to store pixel data
let mut capturer: VecCapturer = monitor.try_into().unwrap();

// you can also get monitor info from a capturer
let dxgi_outdupl_desc = capturer.monitor().dxgi_outdupl_desc();
let dxgi_output_desc = capturer.monitor().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
let info = capturer.capture().unwrap();

// we have some extension methods for the frame info
if info.desktop_updated() {
  println!("captured!");
}
if info.mouse_updated() {
  println!("mouse updated!");
}
if info.pointer_shape_updated() {
  println!("pointer shape updated!");
}

// write to a file
let mut file = File::create("capture.bin").unwrap();
// the buffer is in BGRA32 format
file.write_all(&capturer.buffer).unwrap();

Shared Memory

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

use rusty_duplication::{CapturerBuffer, FrameInfoExt, Scanner, SharedMemoryCapturer};
use std::{fs::File, io::Write, thread, time::Duration};

let monitor = Scanner::new().unwrap().next().unwrap();

// create a shared memory capturer by creating a shared memory with the provided name
let mut capturer = SharedMemoryCapturer::create(monitor, "SharedMemoryName").unwrap();
// you can also use `SharedMemoryCapturer::open` to open an existing shared memory

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

let info = capturer.capture().unwrap();
assert!(info.desktop_updated());

// write to a file
let mut file = File::create("capture.bin").unwrap();
// the buffer is in BGRA32 format
file.write_all(capturer.buffer.as_bytes()).unwrap();

[!NOTE] If your shared memory name starts with Global\, you may need to run your app in administrator mode. See https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga.

Customized Capturer

You can implement CapturerBuffer for your own type to create a customized capturer. You can refer to VecCapturer's implementation.

Examples

Documentation

Credit

This project is based on the following projects:

CHANGELOG

Dependencies

~126MB
~2M SLoC