fix wateramrk

This commit is contained in:
Julian Freeman
2026-01-18 23:55:14 -04:00
parent 0c307c319a
commit a5f1b165fd
3 changed files with 32 additions and 17 deletions

View File

@@ -97,7 +97,7 @@ use image::Pixel;
use rayon::prelude::*;
use std::path::Path;
use imageproc::drawing::draw_text_mut;
use ab_glyph::{FontRef, PxScale, Font};
use ab_glyph::{FontRef, PxScale};
// Embed the font to ensure it's always available without path issues
const FONT_DATA: &[u8] = include_bytes!("../assets/fonts/Roboto-Regular.ttf");
@@ -178,13 +178,13 @@ async fn export_batch(images: Vec<ExportImageTask>, watermark: WatermarkSettings
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 {
// 4. Determine Position (Center based)
let (mut pos_x_pct, mut 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),
Err(_) => (0.5, 0.96), // Default fallback lowered
}
};
@@ -192,12 +192,18 @@ async fn export_batch(images: Vec<ExportImageTask>, watermark: WatermarkSettings
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;
let mut x = (center_x - (final_t_width as f64 / 2.0)) as i32;
let mut y = (center_y - (final_t_height as f64 / 2.0)) as i32;
// Clamp to be visible? imageproc handles out of bounds by clipping.
// 5. Boundary Clamping (Ensure text stays inside image with padding)
let padding = (height as f64 * 0.01).max(5.0) as i32; // 1% padding
let max_x = (width as i32 - final_t_width as i32 - padding).max(padding);
let max_y = (height as i32 - final_t_height as i32 - padding).max(padding);
// 5. Draw
x = x.clamp(padding, max_x);
y = y.clamp(padding, max_y);
// 6. Draw
draw_text_mut(
&mut base_img,
text_color,

View File

@@ -7,6 +7,7 @@ const store = useGalleryStore();
const isDragging = ref(false);
const dragStart = ref({ x: 0, y: 0 });
const imgRef = ref<HTMLImageElement | null>(null);
const containerRef = ref<HTMLElement | null>(null);
const renderHeight = ref(0);
let resizeObserver: ResizeObserver | null = null;
@@ -46,19 +47,21 @@ const position = computed(() => {
});
const onMouseDown = (e: MouseEvent) => {
// Only allow dragging if target is the watermark itself (or its child)
// Actually, user should be able to click watermark to start drag.
// e.preventDefault to stop image drag
e.preventDefault();
isDragging.value = true;
dragStart.value = { x: e.clientX, y: e.clientY };
};
const onMouseMove = (e: MouseEvent) => {
if (!isDragging.value || !store.selectedImage) return;
if (!isDragging.value || !store.selectedImage || !containerRef.value) return;
// Calculate delta in percentage relative to the image container
const container = (e.currentTarget as HTMLElement).closest('.image-container');
if (!container) return;
const rect = containerRef.value.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return;
const rect = container.getBoundingClientRect();
const deltaX = (e.clientX - dragStart.value.x) / rect.width;
const deltaY = (e.clientY - dragStart.value.y) / rect.height;
@@ -66,9 +69,14 @@ const onMouseMove = (e: MouseEvent) => {
let newX = position.value.x + deltaX;
let newY = position.value.y + deltaY;
// Clamp
newX = Math.max(0, Math.min(1, newX));
newY = Math.max(0, Math.min(1, newY));
// Clamp logic (Simple 0-1 clamp for center point first)
// Ideally we should clamp so the box stays inside, but we don't know the exact text width in px easily here without measurement.
// For MVP, clamping center to [0, 1] is "safe enough" to prevent losing it,
// but user asked for "not exceeding boundary".
// Visual clamping: slightly inside 0-1.
const padding = 0.01;
newX = Math.max(padding, Math.min(1 - padding, newX));
newY = Math.max(padding, Math.min(1 - padding, newY));
// Set store to manual mode immediately
store.updateWatermarkSettings({
@@ -97,6 +105,7 @@ const onMouseLeave = () => {
>
<div
v-if="store.selectedImage"
ref="containerRef"
class="relative inline-flex justify-center items-center image-container"
style="max-width: 100%; max-height: 100%;"
>

View File

@@ -29,9 +29,9 @@ export const useGalleryStore = defineStore("gallery", () => {
text: 'Watermark',
color: '#FFFFFF',
opacity: 0.8,
scale: 0.05, // 5% of height default
scale: 0.025, // Reduced from 0.05
manual_override: false,
manual_position: { x: 0.5, y: 0.9 }
manual_position: { x: 0.5, y: 0.96 } // Lowered from 0.9
});
const selectedImage = computed(() => {