Skip to content

Commit

Permalink
feat: windows 支持 app_name (#95)
Browse files Browse the repository at this point in the history
* feat: windows支持app_name

* chore: 修改文档
  • Loading branch information
nashaofu authored Jan 30, 2024
1 parent afc7b46 commit 11c02d1
Show file tree
Hide file tree
Showing 15 changed files with 401 additions and 139 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
components: rustfmt, clippy

- name: Cargo fmt
Expand All @@ -40,3 +41,23 @@ jobs:

- name: Test
run: cargo test
publish:
name: Publish
runs-on: ubuntu-latest
needs:
- lint
steps:
- uses: actions/checkout@v3

- name: Install rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
components: rustfmt, clippy

- name: Publish
if: github.event_name != 'pull_request'
env:
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
run: cargo publish --registry crates-io --token $NPM_TOKEN
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "xcap"
version = "0.0.2"
version = "0.0.3"
edition = "2021"
description = "A cross-platform screen capture library"
description = "XCap is a cross-platform screen capture library written in Rust. It supports Linux (X11, Wayland), MacOS, and Windows. XCap supports screenshot and video recording (to be implemented)."
license = "Apache-2.0"
documentation = "https://docs.rs/xcap"
homepage = "https://github.com/nashaofu/xcap"
Expand All @@ -13,6 +13,7 @@ keywords = ["screen", "monitor", "window", "capture", "image"]

[dependencies]
image = "0.24"
log = "0.4"
thiserror = "1.0"

[target.'cfg(target_os = "macos")'.dependencies]
Expand All @@ -26,6 +27,9 @@ windows = { version = "0.52", features = [
"Win32_Graphics_Dwm",
"Win32_UI_WindowsAndMessaging",
"Win32_Storage_Xps",
"Win32_System_Threading",
"Win32_System_ProcessStatus",
"Win32_Storage_FileSystem",
] }

[target.'cfg(target_os="linux")'.dependencies]
Expand Down
131 changes: 131 additions & 0 deletions README-zh_CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# XCap

[English](README.md) | 简体中文

XCap 是一个使用 Rust 编写的跨平台的屏幕捕获库,它支持 Linux(X11,Wayland)、MacOS 与 Windows。XCap 支持截图与视频录制(待实现)。

## 功能

- 跨平台: 支持 Linux(X11,Wayland)、MacOS 与 Windows。
- 支持多种截图模式: 可以对屏幕与窗口进行截图。
- 支持视频录制:支持对屏幕或窗口进行录制(待实现)。

### 实现状态

| 功能 | Linux(X11) | Linux(Wayland) | MacOS | Windows |
| -------- | ---------- | -------------- | ----- | ------- |
| 屏幕截图 |||||
| 窗口截图 |||||
| 屏幕录制 | 🛠️ | 🛠️ | 🛠️ | 🛠️ |
| 窗口录制 | 🛠️ | 🛠️ | 🛠️ | 🛠️ |

- ✅: 功能可用
- ⛔: 功能可用,但在一些特殊场景下未完全支持
- 🛠️: 待开发

## 例子

- 屏幕截图

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

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

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

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

image
.save(format!("target/monitor-{}.png", normalized(monitor.name())))
.unwrap();
}

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

- 窗口截图

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

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;
}

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/window-{}-{}.png",
i,
normalized(window.title())
))
.unwrap();

i += 1;
}

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

## Linux 系统要求

在 Linux 上,需要安装 `libxcb`, `libxrandr``dbus`.

Debian/Ubuntu:

```sh
apt-get install libxcb1 libxrandr2 libdbus-1-3
```

Alpine:

```sh
apk add libxcb libxrandr dbus
```

ArchLinux:

```sh
pacman -S libxcb libxrandr dbus
```

## License

本项目采用 Apache 许可证。详情请查看 [LICENSE](./LICENSE) 文件。
39 changes: 27 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
# 📷 XCap
# XCap

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.
English | [简体中文](README-zh_CN.md)

XCap is a cross-platform screen capture library written in Rust. It supports Linux (X11, Wayland), MacOS, and Windows. XCap supports screenshot and video recording (to be implemented).

## Features

- Cross-platform support: Windows Mac and Linux.
- Multiple capture modes: screen window.
- Video capture、audio capture soon.
- Cross-platform: Supports Linux (X11, Wayland), MacOS, and Windows.
- Supports multiple screenshot modes: Can take screenshots of the screen and windows.
- Supports video recording: Supports recording of the screen or window (to be implemented).

### Implementation Status

| Feature | Linux(X11) | Linux(Wayland) | MacOS | Windows |
| ---------------- | ---------- | -------------- | ----- | ------- |
| Screen Capture |||||
| Window Capture |||||
| Screen Recording | 🛠️ | 🛠️ | 🛠️ | 🛠️ |
| Window Recording | 🛠️ | 🛠️ | 🛠️ | 🛠️ |

- ✅: Feature available
- ⛔: Feature available, but not fully supported in some special scenarios
- 🛠️: To be developed

## Example
## Examples

- Monitor capture
- Screen Capture

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

fn normalized(filename: &str) -> String {
filename
Expand All @@ -40,11 +55,11 @@ fn main() {
}
```

- Window capture
- Window Capture

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

fn normalized(filename: &str) -> String {
filename
Expand Down Expand Up @@ -89,7 +104,7 @@ fn main() {
}
```

## Linux Requirements
## Linux System Requirements

On Linux, you need to install `libxcb`, `libxrandr`, and `dbus`.

Expand All @@ -113,4 +128,4 @@ pacman -S libxcb libxrandr dbus

## License

This project is licensed under the Apache License. See the [LICENSE](../LICENSE) file for details.
This project is licensed under the Apache License. See the [LICENSE](./LICENSE) file for details.
5 changes: 3 additions & 2 deletions examples/monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ fn main() {

for monitor in monitors {
println!(
"Monitor: {} {} {:?} {:?}",
"Monitor:\n id: {}\n name: {}\n position: {:?}\n size: {:?}\n state:{:?}\n",
monitor.id(),
monitor.name(),
(monitor.x(), monitor.y(), monitor.width(), monitor.height()),
(monitor.x(), monitor.y()),
(monitor.width(), monitor.height()),
(
monitor.rotation(),
monitor.scale_factor(),
Expand Down
5 changes: 3 additions & 2 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ fn main() {

for window in windows {
println!(
"Window: {} {} {} {:?} {:?} {:?}",
"Window:\n id: {}\n title: {}\n app_name: {}\n monitor: {:?}\n position: {:?}\n size {:?}\n state {:?}\n",
window.id(),
window.title(),
window.app_name(),
window.current_monitor().name(),
(window.x(), window.y(), window.width(), window.height()),
(window.x(), window.y()),
(window.width(), window.height()),
(window.is_minimized(), window.is_maximized())
);
}
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
mod error;
mod monitor;
mod utils;
mod window;

#[cfg(target_os = "macos")]
Expand Down
10 changes: 4 additions & 6 deletions src/linux/xorg_capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,7 @@ use xcb::{
Connection,
};

use crate::{
error::{XCapError, XCapResult},
utils::image::vec_to_rgba_image,
};
use crate::error::{XCapError, XCapResult};

fn get_pixel8_rgba(
bytes: &[u8],
Expand Down Expand Up @@ -97,7 +94,6 @@ pub fn xorg_capture(
let bytes = get_image_reply.data();
let depth = get_image_reply.depth();

let mut rgba = vec![0u8; (width * height * 4) as usize];
let pixmap_format = setup
.pixmap_formats()
.iter()
Expand All @@ -115,6 +111,7 @@ pub fn xorg_capture(
_ => return Err(XCapError::new(format!("Unsupported {} depth", depth))),
};

let mut rgba = vec![0u8; (width * height * 4) as usize];
for y in 0..height {
for x in 0..width {
let index = ((y * width + x) * 4) as usize;
Expand All @@ -127,5 +124,6 @@ pub fn xorg_capture(
}
}

vec_to_rgba_image(width, height, rgba)
RgbaImage::from_raw(width, height, rgba)
.ok_or_else(|| XCapError::new("RgbaImage::from_raw failed"))
}
28 changes: 17 additions & 11 deletions src/macos/capture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use core_graphics::{
};
use image::RgbaImage;

use crate::{
error::{XCapError, XCapResult},
utils::image::{bgra_to_rgba_image, remove_extra_data},
};
use crate::error::{XCapError, XCapResult};

pub fn capture(
cg_rect: CGRect,
Expand All @@ -20,12 +17,21 @@ pub fn capture(

let width = cg_image.width();
let height = cg_image.height();
let clean_buf = remove_extra_data(
width,
height,
cg_image.bytes_per_row(),
Vec::from(cg_image.data().bytes()),
);
let bytes = Vec::from(cg_image.data().bytes());

// Some platforms e.g. MacOS can have extra bytes at the end of each row.
// See
// https://github.com/nashaofu/xcap/issues/29
// https://github.com/nashaofu/xcap/issues/38
let mut buffer = Vec::with_capacity(width * height * 4);
for row in bytes.chunks_exact(cg_image.bytes_per_row()) {
buffer.extend_from_slice(&row[..width * 4]);
}

for bgra in buffer.chunks_exact_mut(4) {
bgra.swap(0, 2);
}

bgra_to_rgba_image(width as u32, height as u32, clean_buf)
RgbaImage::from_raw(width as u32, height as u32, buffer)
.ok_or_else(|| XCapError::new("RgbaImage::from_raw failed"))
}
Loading

0 comments on commit 11c02d1

Please sign in to comment.