feat: 截图功能验证。

截图需要 700 ms,转换成 webp 3 s。
This commit is contained in:
2022-11-16 21:33:49 +08:00
commit fbb222ad23
39 changed files with 5301 additions and 0 deletions

4
src-tauri/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
# Generated by Cargo
# will have compiled files and executables
/target/

3781
src-tauri/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

32
src-tauri/Cargo.toml Normal file
View File

@ -0,0 +1,32 @@
[package]
name = "screen-bg-light-desktop"
version = "0.0.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
edition = "2021"
rust-version = "1.57"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
tauri-build = { version = "1.1", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.1", features = ["api-all"] }
scrap = "0.5"
repng = "0.2.2"
bmp = "0.5.0"
webp = "0.2.2"
base64 = "0.13.1"
[features]
# by default Tauri runs in production mode
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
default = [ "custom-protocol" ]
# this feature is used used for production builds where `devPath` points to the filesystem
# DO NOT remove this
custom-protocol = [ "tauri/custom-protocol" ]

3
src-tauri/build.rs Normal file
View File

@ -0,0 +1,3 @@
fn main() {
tauri_build::build()
}

BIN
src-tauri/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
src-tauri/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 974 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
src-tauri/icons/icon.icns Normal file

Binary file not shown.

BIN
src-tauri/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

BIN
src-tauri/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

82
src-tauri/src/main.rs Normal file
View File

@ -0,0 +1,82 @@
#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
use bmp::{Image, Pixel};
use scrap::{Capturer, Display};
use std::io::ErrorKind::WouldBlock;
use std::path::Path;
use std::thread;
use std::time::Duration;
use std::{fs, time::Instant};
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(name: &str) -> String {
format!("Hello, {}! You've been greeted from Rust!", name)
}
#[tauri::command]
fn take_snapshot() -> String {
let one_second = Duration::new(1, 0);
let one_frame = one_second / 60;
let display = Display::primary().expect("Couldn't find primary display.");
let mut capturer = Capturer::new(display).expect("Couldn't begin capture.");
let (w, h) = (capturer.width(), capturer.height());
loop {
// Wait until there's a frame.
let start = Instant::now();
let buffer = match capturer.frame() {
Ok(buffer) => buffer,
Err(error) => {
if error.kind() == WouldBlock {
// Keep spinning.
thread::sleep(one_frame);
continue;
} else {
panic!("Error: {}", error);
}
}
};
println!("Captured! Saving...");
// Flip the ARGB image into a BGRA image.
let mut bitflipped = Vec::with_capacity(w * h * 3);
let stride = buffer.len() / h;
let mut img = Image::new(w as u32, h as u32);
for y in 0..h {
for x in 0..w {
let i = stride * y + 4 * x;
bitflipped.extend_from_slice(&[buffer[i + 2], buffer[i + 1], buffer[i]]);
// img.set_pixel(
// x as u32,
// y as u32,
// Pixel::new(buffer[i + 2], buffer[i + 1], buffer[i]),
// );
}
}
let webp_memory =
webp::Encoder::from_rgb(bitflipped.as_slice(), w as u32, h as u32).encode(100.0);
let encode_text = base64::encode(&*webp_memory);
// let output_path = Path::new("assets").join("lake").with_extension("webp");
// std::fs::write(&output_path, &*webp_memory).unwrap();
println!("运行耗时: {:?}", start.elapsed());
return encode_text;
}
}
fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet, take_snapshot])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}

65
src-tauri/tauri.conf.json Normal file
View File

@ -0,0 +1,65 @@
{
"build": {
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"devPath": "http://localhost:1420",
"distDir": "../dist"
},
"package": {
"productName": "screen-bg-light-desktop",
"version": "0.0.0"
},
"tauri": {
"allowlist": {
"all": true
},
"bundle": {
"active": true,
"category": "DeveloperTool",
"copyright": "",
"deb": {
"depends": []
},
"externalBin": [],
"icon": [
"icons/32x32.png",
"icons/128x128.png",
"icons/128x128@2x.png",
"icons/icon.icns",
"icons/icon.ico"
],
"identifier": "com.tauri.dev",
"longDescription": "",
"macOS": {
"entitlements": null,
"exceptionDomain": "",
"frameworks": [],
"providerShortName": null,
"signingIdentity": null
},
"resources": [],
"shortDescription": "",
"targets": "all",
"windows": {
"certificateThumbprint": null,
"digestAlgorithm": "sha256",
"timestampUrl": ""
}
},
"security": {
"csp": null
},
"updater": {
"active": false
},
"windows": [
{
"fullscreen": false,
"height": 600,
"resizable": true,
"title": "screen-bg-light-desktop",
"width": 800
}
]
}
}