diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 9decacb..0cf76b9 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -35,15 +35,9 @@ fn generate_thumbnail(original_path: &Path) -> Option { } // Generate - // Use image reader to be faster? open is fine. if let Ok(img) = image::open(original_path) { - // Resize to height 200, preserve ratio let thumb = img.thumbnail(u32::MAX, 200); - // Save as jpeg with quality 80 - let mut file = fs::File::create(&thumb_path).ok()?; - // thumb.write_to(&mut file, image::ImageOutputFormat::Jpeg(80)).ok()?; - // write_to might be slow due to encoding, but parallel execution helps. - // save directly + let _file = fs::File::create(&thumb_path).ok()?; thumb.save_with_format(&thumb_path, image::ImageFormat::Jpeg).ok()?; return Some(thumb_path.to_string_lossy().to_string()); @@ -165,30 +159,28 @@ async fn export_batch(images: Vec, watermark: WatermarkSettings // 2. Measure Text let scaled_font = PxScale::from(scale_px); - let (t_width, t_height) = imageproc::drawing::text_size(scaled_font, &font, &watermark.text); + 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 (Center based) - let (mut pos_x_pct, mut pos_y_pct) = if watermark.manual_override { + 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.96), // Default fallback lowered + Err(_) => (0.5, 0.96), } }; - // Calculate top-left coordinate for draw_text_mut (it expects top-left, not center) + // Calculate top-left coordinate for draw_text_mut let center_x = width as f64 * pos_x_pct; let center_y = height as f64 * pos_y_pct; @@ -203,7 +195,21 @@ async fn export_batch(images: Vec, watermark: WatermarkSettings x = x.clamp(padding, max_x); y = y.clamp(padding, max_y); - // 6. Draw + // 6. Draw Stroke (Simple 4-direction offset for black outline) + let stroke_color = image::Rgba([0, 0, 0, text_color[3]]); + for offset in [(-1, -1), (-1, 1), (1, -1), (1, 1)] { + draw_text_mut( + &mut base_img, + stroke_color, + x + offset.0, + y + offset.1, + final_scale, + &font, + &watermark.text, + ); + } + + // 7. Draw Main Text draw_text_mut( &mut base_img, text_color, diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index f7fe4c9..bc358d3 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -13,8 +13,8 @@ "windows": [ { "title": "watermark-wizard", - "width": 800, - "height": 600 + "width": 1650, + "height": 1000 } ], "security": { diff --git a/src/components/HeroView.vue b/src/components/HeroView.vue index 42e3cbb..7568bf3 100644 --- a/src/components/HeroView.vue +++ b/src/components/HeroView.vue @@ -160,6 +160,10 @@ const onMouseLeave = () => { } span { - text-shadow: 0 1px 3px rgba(0,0,0,0.5); + text-shadow: + -1px -1px 0 #000, + 1px -1px 0 #000, + -1px 1px 0 #000, + 1px 1px 0 #000; }