phase 1 & 2 add text mark
This commit is contained in:
187
src-tauri/Cargo.lock
generated
187
src-tauri/Cargo.lock
generated
@@ -2,6 +2,22 @@
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph"
|
||||
version = "0.2.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01c0457472c38ea5bd1c3b5ada5e368271cb550be7a4ca4a0b4634e9913f6cc2"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"owned_ttf_parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph_rasterizer"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
|
||||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.1"
|
||||
@@ -65,6 +81,15 @@ version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "approx"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.2"
|
||||
@@ -1175,8 +1200,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
"libc",
|
||||
"wasi 0.11.1+wasi-snapshot-preview1",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1668,6 +1695,24 @@ dependencies = [
|
||||
"quick-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imageproc"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2393fb7808960751a52e8a154f67e7dd3f8a2ef9bd80d1553078a7b4e8ed3f0d"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"approx",
|
||||
"getrandom 0.2.17",
|
||||
"image",
|
||||
"itertools 0.12.1",
|
||||
"nalgebra",
|
||||
"num",
|
||||
"rand 0.8.5",
|
||||
"rand_distr",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "imgref"
|
||||
version = "1.12.0"
|
||||
@@ -1733,6 +1778,15 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.14.0"
|
||||
@@ -1920,6 +1974,12 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.12"
|
||||
@@ -1997,6 +2057,16 @@ version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
|
||||
|
||||
[[package]]
|
||||
name = "matrixmultiply"
|
||||
version = "0.3.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"rawpointer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-rayon"
|
||||
version = "0.1.1"
|
||||
@@ -2080,6 +2150,21 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nalgebra"
|
||||
version = "0.32.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5c17de023a86f59ed79891b2e5d5a94c705dbe904a5b5c9c952ea6221b03e4"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"matrixmultiply",
|
||||
"num-complex",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
"simba",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ndk"
|
||||
version = "0.9.0"
|
||||
@@ -2137,6 +2222,20 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
@@ -2147,6 +2246,15 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@@ -2173,6 +2281,17 @@ dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
@@ -2191,6 +2310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2439,6 +2559,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
|
||||
dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.18.3"
|
||||
@@ -2953,6 +3082,16 @@ dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
@@ -2987,7 +3126,7 @@ dependencies = [
|
||||
"built",
|
||||
"cfg-if",
|
||||
"interpolate_name",
|
||||
"itertools",
|
||||
"itertools 0.14.0",
|
||||
"libc",
|
||||
"libfuzzer-sys",
|
||||
"log",
|
||||
@@ -3027,6 +3166,12 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
||||
|
||||
[[package]]
|
||||
name = "rawpointer"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.11.0"
|
||||
@@ -3202,6 +3347,15 @@ version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
|
||||
|
||||
[[package]]
|
||||
name = "safe_arch"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "same-file"
|
||||
version = "1.0.6"
|
||||
@@ -3483,6 +3637,19 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "simba"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "061507c94fc6ab4ba1c9a0305018408e312e17c041eb63bef8aa726fa33aceae"
|
||||
dependencies = [
|
||||
"approx",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"paste",
|
||||
"wide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.8"
|
||||
@@ -4334,6 +4501,12 @@ version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31"
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
@@ -4607,7 +4780,9 @@ dependencies = [
|
||||
name = "watermark-wizard"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ab_glyph",
|
||||
"image",
|
||||
"imageproc",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -4712,6 +4887,16 @@ version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
|
||||
|
||||
[[package]]
|
||||
name = "wide"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"safe_arch",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
@@ -21,7 +21,9 @@ tauri-build = { version = "2", features = [] }
|
||||
tauri = { version = "2", features = ["protocol-asset"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
image = "0.25"
|
||||
image = { version = "0.25", features = ["png", "jpeg", "webp"] }
|
||||
rayon = "1.10"
|
||||
tauri-plugin-dialog = "2"
|
||||
imageproc = "0.25"
|
||||
ab_glyph = "0.2.23"
|
||||
|
||||
|
||||
BIN
src-tauri/assets/fonts/Roboto-Regular.ttf
Normal file
BIN
src-tauri/assets/fonts/Roboto-Regular.ttf
Normal file
Binary file not shown.
@@ -34,6 +34,13 @@ fn scan_dir(path: String) -> Result<Vec<ImageItem>, String> {
|
||||
|
||||
use image::GenericImageView;
|
||||
use image::Pixel;
|
||||
use rayon::prelude::*;
|
||||
use std::path::Path;
|
||||
use imageproc::drawing::draw_text_mut;
|
||||
use ab_glyph::{FontRef, PxScale, Font};
|
||||
|
||||
// Embed the font to ensure it's always available without path issues
|
||||
const FONT_DATA: &[u8] = include_bytes!("../assets/fonts/Roboto-Regular.ttf");
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
struct ZcaResult {
|
||||
@@ -42,13 +49,132 @@ struct ZcaResult {
|
||||
zone: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ExportImageTask {
|
||||
path: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct WatermarkSettings {
|
||||
#[serde(rename = "type")]
|
||||
_w_type: String, // 'text' (image is deprecated for now per user request, but keeping struct flexible)
|
||||
text: String, // Was 'source'
|
||||
color: String, // Hex code e.g. "#FFFFFF"
|
||||
opacity: f64,
|
||||
scale: f64, // Font size relative to image height (e.g., 0.05 = 5% of height)
|
||||
manual_override: bool,
|
||||
manual_position: ManualPosition,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ManualPosition {
|
||||
x: f64,
|
||||
y: f64,
|
||||
}
|
||||
|
||||
fn parse_hex_color(hex: &str) -> image::Rgba<u8> {
|
||||
let hex = hex.trim_start_matches('#');
|
||||
let r = u8::from_str_radix(&hex[0..2], 16).unwrap_or(255);
|
||||
let g = u8::from_str_radix(&hex[2..4], 16).unwrap_or(255);
|
||||
let b = u8::from_str_radix(&hex[4..6], 16).unwrap_or(255);
|
||||
image::Rgba([r, g, b, 255])
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
let img = image::open(&path).map_err(|e| e.to_string())?;
|
||||
async fn export_batch(images: Vec<ExportImageTask>, watermark: WatermarkSettings, output_dir: String) -> Result<String, String> {
|
||||
let font = FontRef::try_from_slice(FONT_DATA).map_err(|e| format!("Font error: {}", e))?;
|
||||
let base_color = parse_hex_color(&watermark.color);
|
||||
|
||||
// Calculate final color with opacity
|
||||
// imageproc draws with the exact color given. To support opacity, we need to handle it.
|
||||
// However, draw_text_mut blends. If we provide an Rgba with alpha < 255, it should blend.
|
||||
let alpha = (watermark.opacity * 255.0) as u8;
|
||||
let text_color = image::Rgba([base_color[0], base_color[1], base_color[2], alpha]);
|
||||
|
||||
let results: Vec<Result<(), String>> = images.par_iter().map(|task| {
|
||||
let input_path = Path::new(&task.path);
|
||||
let img_result = image::open(input_path);
|
||||
|
||||
if let Ok(dynamic_img) = img_result {
|
||||
let mut base_img = dynamic_img.to_rgba8();
|
||||
let (width, height) = base_img.dimensions();
|
||||
|
||||
// 1. Calculate Font Scale
|
||||
// watermark.scale is percentage of image height. e.g. 0.05
|
||||
let mut scale_px = height as f32 * watermark.scale as f32;
|
||||
|
||||
// 2. Measure Text
|
||||
let scaled_font = PxScale::from(scale_px);
|
||||
let (t_width, t_height) = imageproc::drawing::text_size(scaled_font, &font, &watermark.text);
|
||||
|
||||
// 3. Ensure it fits width (Padding 5%)
|
||||
let max_width = (width as f32 * 0.95) as u32;
|
||||
if t_width > max_width {
|
||||
let ratio = max_width as f32 / t_width as f32;
|
||||
scale_px *= ratio;
|
||||
// Re-measure isn't strictly necessary for center calc if we assume linear scaling,
|
||||
// but let's be safe for variable width fonts? Actually text_size scales linearly.
|
||||
}
|
||||
let final_scale = PxScale::from(scale_px);
|
||||
let (final_t_width, final_t_height) = imageproc::drawing::text_size(final_scale, &font, &watermark.text);
|
||||
|
||||
// 4. Determine Position
|
||||
let (pos_x_pct, pos_y_pct) = if watermark.manual_override {
|
||||
(watermark.manual_position.x, watermark.manual_position.y)
|
||||
} else {
|
||||
match calculate_zca_internal(&dynamic_img) {
|
||||
Ok(res) => (res.x, res.y),
|
||||
Err(_) => (0.5, 0.95),
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate top-left coordinate for draw_text_mut (it expects top-left, not center)
|
||||
let center_x = width as f64 * pos_x_pct;
|
||||
let center_y = height as f64 * pos_y_pct;
|
||||
|
||||
let x = (center_x - (final_t_width as f64 / 2.0)) as i32;
|
||||
let y = (center_y - (final_t_height as f64 / 2.0)) as i32;
|
||||
|
||||
// Clamp to be visible? imageproc handles out of bounds by clipping.
|
||||
|
||||
// 5. Draw
|
||||
draw_text_mut(
|
||||
&mut base_img,
|
||||
text_color,
|
||||
x,
|
||||
y,
|
||||
final_scale,
|
||||
&font,
|
||||
&watermark.text,
|
||||
);
|
||||
|
||||
// Save
|
||||
let file_name = input_path.file_name().unwrap_or_default();
|
||||
let output_path = Path::new(&output_dir).join(file_name);
|
||||
base_img.save(output_path).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
} else {
|
||||
Err(format!("Failed to open {}", task.path))
|
||||
}
|
||||
}).collect();
|
||||
|
||||
let failures: Vec<String> = results.into_iter().filter_map(|r| r.err()).collect();
|
||||
|
||||
if failures.is_empty() {
|
||||
Ok("All images processed successfully".to_string())
|
||||
} else {
|
||||
Err(format!("Completed with errors: {:?}", failures))
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to reuse logic (adapted from command)
|
||||
fn calculate_zca_internal(img: &image::DynamicImage) -> Result<ZcaResult, String> {
|
||||
let (width, height) = img.dimensions();
|
||||
|
||||
let bottom_start_y = (height as f64 * 0.8) as u32;
|
||||
let zone_height = height - bottom_start_y;
|
||||
let zone_width = width / 3;
|
||||
|
||||
let zones = [
|
||||
("Left", 0, bottom_start_y),
|
||||
("Center", zone_width, bottom_start_y),
|
||||
@@ -57,10 +183,11 @@ fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
|
||||
let mut min_std_dev = f64::MAX;
|
||||
let mut best_zone = "Center";
|
||||
let mut best_pos = (0.5, 0.9); // Default center
|
||||
let mut best_pos = (0.5, 0.95);
|
||||
|
||||
for (name, start_x, start_y) in zones.iter() {
|
||||
let mut luma_values = Vec::with_capacity((zone_width * zone_height) as usize);
|
||||
|
||||
for y in *start_y..height {
|
||||
for x in *start_x..(*start_x + zone_width) {
|
||||
if x >= width { continue; }
|
||||
@@ -73,7 +200,7 @@ fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
|
||||
let count = luma_values.len() as f64;
|
||||
if count == 0.0 { continue; }
|
||||
|
||||
|
||||
let mean = luma_values.iter().sum::<f64>() / count;
|
||||
let variance = luma_values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / count;
|
||||
let std_dev = variance.sqrt();
|
||||
@@ -82,8 +209,6 @@ fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
min_std_dev = std_dev;
|
||||
best_zone = name;
|
||||
let center_x_px = *start_x as f64 + (zone_width as f64 / 2.0);
|
||||
// Position closer to bottom (75% of the zone height instead of 50%)
|
||||
// Zone starts at 80%. Height is 20%. 0.8 + 0.2 * 0.75 = 0.95
|
||||
let center_y_px = *start_y as f64 + (zone_height as f64 * 0.75);
|
||||
best_pos = (center_x_px / width as f64, center_y_px / height as f64);
|
||||
}
|
||||
@@ -96,12 +221,17 @@ fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
})
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||
let img = image::open(&path).map_err(|e| e.to_string())?;
|
||||
calculate_zca_internal(&img)
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.invoke_handler(tauri::generate_handler![scan_dir, get_zca_suggestion])
|
||||
.invoke_handler(tauri::generate_handler![scan_dir, get_zca_suggestion, export_batch])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user