Skip to content

Commit

Permalink
feat: 修改名称
Browse files Browse the repository at this point in the history
  • Loading branch information
nashaofu committed Jan 21, 2024
1 parent bb82dc3 commit ff514c6
Show file tree
Hide file tree
Showing 22 changed files with 170 additions and 117 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ version = "0.0.1"
edition = "2021"
description = "A cross-platform screen capture library"
license = "Apache-2.0"
documentation = "https://docs.rs/screen-capture"
homepage = "https://github.com/nashaofu/screen-capture"
repository = "https://github.com/nashaofu/screen-capture.git"
documentation = "https://docs.rs/xcap"
homepage = "https://github.com/nashaofu/xcap"
repository = "https://github.com/nashaofu/xcap.git"
keywords = [
"screen",
"monitor",
Expand Down
85 changes: 69 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,90 @@
# 📷 screen-capture
# 📷 xcap

screen-capture is a cross-platform screen capture library for MacOS, Windows, Linux (X11, Wayland) written in Rust. It provides a simple API for capturing screen capture of a screen or a specific area of a screen.
xcap is a cross-platform screen capture library for MacOS, Windows, Linux (X11, Wayland) written in Rust. It provides a simple API for capturing screen capture of a screen or a specific area of a screen.

## Features

- Cross-platform support: Windows Mac and Linux.
- Multiple capture modes: screen window.
- Video capture、audio capture soon.

## Example

The following example shows how to capture screen capture of all screens and a specific area of a screen.
- Monitor capture

```rust
use screen_capture::Screen;
use xcap::Monitor;
use std::time::Instant;

fn normalized(filename: &str) -> String {
filename
.replace("|", "")
.replace("\\", "")
.replace(":", "")
.replace("/", "")
}

fn main() {
let start = Instant::now();
let screens = Screen::all().unwrap();
let monitors = Monitor::all().unwrap();

for monitor in monitors {
let image = monitor.capture_image().unwrap();

for screen in screens {
println!("capturer {screen:?}");
let mut image = screen.capture().unwrap();
image
.save(format!("target/{}.png", screen.screen_info.id))
.save(format!("target/monitor-{}.png", normalized(monitor.name())))
.unwrap();
}

println!("运行耗时: {:?}", start.elapsed());
}
```

- Window capture

```rust
use xcap::Window;
use std::time::Instant;

fn normalized(filename: &str) -> String {
filename
.replace("|", "")
.replace("\\", "")
.replace(":", "")
.replace("/", "")
}

fn main() {
let start = Instant::now();
let windows = Window::all().unwrap();

let mut i = 0;

for window in windows {
// 最小化的窗口不能截屏
if window.is_minimized() {
continue;
}

image = screen.capture_area(300, 300, 300, 300).unwrap();
println!(
"Window: {:?} {:?} {:?}",
window.title(),
(window.x(), window.y(), window.width(), window.height()),
(window.is_minimized(), window.is_maximized())
);

let image = window.capture_image().unwrap();
image
.save(format!("target/{}-2.png", screen.screen_info.id))
.save(format!(
"target/window-{}-{}.png",
i,
normalized(window.title())
))
.unwrap();
}

let screen = Screen::from_point(100, 100).unwrap();
println!("capturer {screen:?}");
i += 1;
}

let image = screen.capture_area(300, 300, 300, 300).unwrap();
image.save("target/capture_screen_with_point.png").unwrap();
println!("运行耗时: {:?}", start.elapsed());
}
```
Expand Down
2 changes: 1 addition & 1 deletion examples/monitor_capture.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use screen_capture::Monitor;
use xcap::Monitor;
use std::time::Instant;

fn normalized(filename: &str) -> String {
Expand Down
2 changes: 1 addition & 1 deletion examples/window.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use screen_capture::Window;
use xcap::Window;
use std::time::Instant;

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion examples/window_capture.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use screen_capture::Window;
use xcap::Window;
use std::time::Instant;

fn normalized(filename: &str) -> String {
Expand Down
12 changes: 6 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use thiserror::Error;

#[derive(Debug, Error)]
pub enum ScreenCaptureError {
pub enum XCapError {
#[error("{0}")]
Error(String),

Expand Down Expand Up @@ -39,17 +39,17 @@ pub enum ScreenCaptureError {
StdStringFromUtf16Error(#[from] std::string::FromUtf16Error),
}

impl ScreenCaptureError {
impl XCapError {
pub fn new<S: ToString>(err: S) -> Self {
ScreenCaptureError::Error(err.to_string())
XCapError::Error(err.to_string())
}
}

#[cfg(target_os = "macos")]
impl From<core_graphics::display::CGError> for ScreenCaptureError {
impl From<core_graphics::display::CGError> for XCapError {
fn from(value: core_graphics::display::CGError) -> Self {
ScreenCaptureError::CoreGraphicsDisplayCGError(value)
XCapError::CoreGraphicsDisplayCGError(value)
}
}

pub type ScreenCaptureResult<T> = Result<T, ScreenCaptureError>;
pub type XCapResult<T> = Result<T, XCapError>;
8 changes: 4 additions & 4 deletions src/linux/capture.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use image::RgbaImage;
use std::env::var_os;

use crate::error::ScreenCaptureResult;
use crate::error::XCapResult;

use super::{
impl_monitor::ImplMonitor, impl_window::ImplWindow, wayland_capture::wayland_capture,
Expand All @@ -22,7 +22,7 @@ fn wayland_detect() -> bool {
xdg_session_type.eq("wayland") || wayland_display.to_lowercase().contains("wayland")
}

pub fn capture_monitor(impl_monitor: &ImplMonitor) -> ScreenCaptureResult<RgbaImage> {
pub fn capture_monitor(impl_monitor: &ImplMonitor) -> XCapResult<RgbaImage> {
if wayland_detect() {
wayland_capture(impl_monitor)
} else {
Expand All @@ -35,7 +35,7 @@ pub fn capture_monitor(impl_monitor: &ImplMonitor) -> ScreenCaptureResult<RgbaIm
}
}

pub fn capture_window(impl_window: &ImplWindow) -> ScreenCaptureResult<RgbaImage> {
pub fn capture_window(impl_window: &ImplWindow) -> XCapResult<RgbaImage> {
let width = impl_window.width;
let height = impl_window.height;

Expand All @@ -48,7 +48,7 @@ pub fn capture_window(impl_window: &ImplWindow) -> ScreenCaptureResult<RgbaImage
// y: i32,
// width: u32,
// height: u32,
// ) -> ScreenCaptureResult<RgbaImage> {
// ) -> XCapResult<RgbaImage> {
// if wayland_detect() {
// wayland_capture_screen_area(screen_info, x, y, width, height)
// } else {
Expand Down
26 changes: 13 additions & 13 deletions src/linux/impl_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use xcb::{
Connection, Xid,
};

use crate::error::{ScreenCaptureError, ScreenCaptureResult};
use crate::error::{XCapError, XCapResult};

use super::capture::capture_monitor;

Expand Down Expand Up @@ -55,7 +55,7 @@ fn get_current_frequency(mode_infos: &[ModeInfo], mode: Mode) -> f32 {
}
}

fn get_scale_factor(conn: &Connection, screen: &Screen) -> ScreenCaptureResult<f32> {
fn get_scale_factor(conn: &Connection, screen: &Screen) -> XCapResult<f32> {
let xft_dpi_prefix = "Xft.dpi:\t";

let get_property_cookie = conn.send_request(&GetProperty {
Expand All @@ -74,13 +74,13 @@ fn get_scale_factor(conn: &Connection, screen: &Screen) -> ScreenCaptureResult<f
let xft_dpi = resource_manager
.split('\n')
.find(|s| s.starts_with(xft_dpi_prefix))
.ok_or_else(|| ScreenCaptureError::new("Xft.dpi parse failed"))?
.ok_or_else(|| XCapError::new("Xft.dpi parse failed"))?
.strip_prefix(xft_dpi_prefix)
.ok_or_else(|| ScreenCaptureError::new("Xft.dpi parse failed"))?;
.ok_or_else(|| XCapError::new("Xft.dpi parse failed"))?;

let dpi = xft_dpi
.parse::<f32>()
.map_err(|err| ScreenCaptureError::new(err))?;
.map_err(|err| XCapError::new(err))?;

Ok(dpi / 96.0)
}
Expand All @@ -89,7 +89,7 @@ fn get_rotation_frequency(
conn: &Connection,
mode_infos: &[ModeInfo],
output: &Output,
) -> ScreenCaptureResult<(f32, f32)> {
) -> XCapResult<(f32, f32)> {
let get_output_info_cookie = conn.send_request(&GetOutputInfo {
output: *output,
config_timestamp: 0,
Expand Down Expand Up @@ -128,7 +128,7 @@ impl ImplMonitor {
rotation: f32,
scale_factor: f32,
frequency: f32,
) -> ScreenCaptureResult<ImplMonitor> {
) -> XCapResult<ImplMonitor> {
let get_output_info_cookie = conn.send_request(&GetOutputInfo {
output: *output,
config_timestamp: CURRENT_TIME,
Expand All @@ -151,15 +151,15 @@ impl ImplMonitor {
})
}

pub fn all() -> ScreenCaptureResult<Vec<ImplMonitor>> {
pub fn all() -> XCapResult<Vec<ImplMonitor>> {
let (conn, index) = Connection::connect(None)?;

let setup = conn.get_setup();

let screen = setup
.roots()
.nth(index as usize)
.ok_or_else(|| ScreenCaptureError::new("Not found screen"))?;
.ok_or_else(|| XCapError::new("Not found screen"))?;

let scale_factor = get_scale_factor(&conn, screen).unwrap_or(1.0);

Expand All @@ -186,7 +186,7 @@ impl ImplMonitor {
let output = monitor_info
.outputs()
.get(0)
.ok_or_else(|| ScreenCaptureError::new("Not found output"))?;
.ok_or_else(|| XCapError::new("Not found output"))?;

let (rotation, frequency) =
get_rotation_frequency(&conn, mode_infos, output).unwrap_or((0.0, 0.0));
Expand All @@ -205,7 +205,7 @@ impl ImplMonitor {
Ok(impl_monitor)
}

pub fn from_point(x: i32, y: i32) -> ScreenCaptureResult<ImplMonitor> {
pub fn from_point(x: i32, y: i32) -> XCapResult<ImplMonitor> {
let impl_monitors = ImplMonitor::all()?;

let impl_monitor = impl_monitors
Expand All @@ -216,14 +216,14 @@ impl ImplMonitor {
&& y >= impl_monitor.y
&& y < impl_monitor.y + impl_monitor.height as i32
})
.ok_or_else(|| ScreenCaptureError::new("Get screen info failed"))?;
.ok_or_else(|| XCapError::new("Get screen info failed"))?;

Ok(impl_monitor.clone())
}
}

impl ImplMonitor {
pub fn capture_image(&self) -> ScreenCaptureResult<RgbaImage> {
pub fn capture_image(&self) -> XCapResult<RgbaImage> {
capture_monitor(self)
}
}
16 changes: 8 additions & 8 deletions src/linux/impl_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use xcb::{
Connection, Xid,
};

use crate::error::{ScreenCaptureError, ScreenCaptureResult};
use crate::error::{XCapError, XCapResult};

use super::{capture::capture_window, impl_monitor::ImplMonitor, utils::Rect};

Expand All @@ -28,7 +28,7 @@ pub(crate) struct ImplWindow {
pub is_maximized: bool,
}

fn get_atom(conn: &Connection, name: &str) -> ScreenCaptureResult<Atom> {
fn get_atom(conn: &Connection, name: &str) -> XCapResult<Atom> {
let atom_cookie = conn.send_request(&InternAtom {
only_if_exists: true,
name: name.as_bytes(),
Expand All @@ -37,7 +37,7 @@ fn get_atom(conn: &Connection, name: &str) -> ScreenCaptureResult<Atom> {
let atom = atom_reply.atom();

if atom == ATOM_NONE {
return Err(ScreenCaptureError::new(format!("{} not supported", name)));
return Err(XCapError::new(format!("{} not supported", name)));
}

Ok(atom)
Expand All @@ -50,7 +50,7 @@ fn get_window_property(
r#type: Atom,
long_offset: u32,
long_length: u32,
) -> ScreenCaptureResult<GetPropertyReply> {
) -> XCapResult<GetPropertyReply> {
let window_property_cookie = conn.send_request(&GetProperty {
delete: false,
window,
Expand All @@ -70,7 +70,7 @@ impl ImplWindow {
conn: &Connection,
window: &Window,
impl_monitors: &Vec<ImplMonitor>,
) -> ScreenCaptureResult<ImplWindow> {
) -> XCapResult<ImplWindow> {
let title = {
let get_title_reply =
get_window_property(conn, *window, ATOM_WM_NAME, ATOM_STRING, 0, 1024)?;
Expand Down Expand Up @@ -116,7 +116,7 @@ impl ImplWindow {
let mut max_area = 0;
let mut find_result = impl_monitors
.get(0)
.ok_or(ScreenCaptureError::new("Get screen info failed"))?;
.ok_or(XCapError::new("Get screen info failed"))?;

let window_rect = Rect::new(x, y, width, height);

Expand Down Expand Up @@ -182,7 +182,7 @@ impl ImplWindow {
})
}

pub fn all() -> ScreenCaptureResult<Vec<ImplWindow>> {
pub fn all() -> XCapResult<Vec<ImplWindow>> {
let (conn, _) = Connection::connect(None)?;
let setup = conn.get_setup();

Expand Down Expand Up @@ -215,7 +215,7 @@ impl ImplWindow {
}

impl ImplWindow {
pub fn capture_image(&self) -> ScreenCaptureResult<RgbaImage> {
pub fn capture_image(&self) -> XCapResult<RgbaImage> {
capture_window(&self)
}
}
Loading

0 comments on commit ff514c6

Please sign in to comment.