seperate color
This commit is contained in:
@@ -109,6 +109,7 @@ struct ExportImageTask {
|
||||
manual_position: Option<ManualPosition>,
|
||||
scale: Option<f64>,
|
||||
opacity: Option<f64>,
|
||||
color: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
@@ -141,9 +142,8 @@ fn parse_hex_color(hex: &str) -> image::Rgba<u8> {
|
||||
#[tauri::command]
|
||||
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);
|
||||
|
||||
// Note: opacity and final text color are now calculated per-task
|
||||
// Note: Settings are now resolved per-task
|
||||
|
||||
let results: Vec<Result<(), String>> = images.par_iter().map(|task| {
|
||||
let input_path = Path::new(&task.path);
|
||||
@@ -156,8 +156,10 @@ async fn export_batch(images: Vec<ExportImageTask>, watermark: WatermarkSettings
|
||||
// Determine effective settings (Task > Global)
|
||||
let eff_scale = task.scale.unwrap_or(watermark.scale);
|
||||
let eff_opacity = task.opacity.unwrap_or(watermark.opacity);
|
||||
let eff_color_hex = task.color.as_ref().unwrap_or(&watermark.color);
|
||||
|
||||
// Calculate final color with effective opacity
|
||||
// Calculate final color
|
||||
let base_color = parse_hex_color(eff_color_hex);
|
||||
let alpha = (eff_opacity * 255.0) as u8;
|
||||
let text_color = image::Rgba([base_color[0], base_color[1], base_color[2], alpha]);
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ async function exportBatch() {
|
||||
path: img.path,
|
||||
manual_position: img.manualPosition || null,
|
||||
scale: img.scale || null,
|
||||
opacity: img.opacity || null
|
||||
opacity: img.opacity || null,
|
||||
color: img.color || null
|
||||
}));
|
||||
|
||||
// Pass dummy globals for rust struct compatibility
|
||||
|
||||
@@ -75,6 +75,7 @@ const position = computed(() => {
|
||||
|
||||
const effectiveScale = computed(() => store.selectedImage?.scale ?? store.watermarkSettings.scale);
|
||||
const effectiveOpacity = computed(() => store.selectedImage?.opacity ?? store.watermarkSettings.opacity);
|
||||
const effectiveColor = computed(() => store.selectedImage?.color ?? store.watermarkSettings.color);
|
||||
|
||||
const onMouseDown = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
@@ -159,7 +160,7 @@ const onMouseLeave = () => {
|
||||
top: (position.y * 100) + '%',
|
||||
transform: 'translate(-50%, -50%)',
|
||||
opacity: effectiveOpacity,
|
||||
color: store.watermarkSettings.color,
|
||||
color: effectiveColor,
|
||||
/* Scale based on HEIGHT of the IMAGE */
|
||||
fontSize: (imageRect.height * effectiveScale) + 'px',
|
||||
height: '0px',
|
||||
|
||||
@@ -28,8 +28,19 @@ const currentOpacity = computed({
|
||||
}
|
||||
});
|
||||
|
||||
const currentColor = computed({
|
||||
get: () => store.selectedImage?.color ?? store.watermarkSettings.color,
|
||||
set: (val) => {
|
||||
if (store.selectedIndex >= 0) {
|
||||
store.setImageSetting(store.selectedIndex, 'color', val);
|
||||
} else {
|
||||
store.updateWatermarkSettings({ color: val });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const applyAll = () => {
|
||||
if (confirm("Apply current size and opacity settings to ALL images? This will reset individual adjustments.")) {
|
||||
if (confirm("Apply current settings (Size, Opacity, Color) to ALL images?")) {
|
||||
store.applySettingsToAll();
|
||||
}
|
||||
};
|
||||
@@ -44,7 +55,7 @@ const applyAll = () => {
|
||||
</div>
|
||||
<button
|
||||
@click="applyAll"
|
||||
title="Apply Size & Opacity to All Images"
|
||||
title="Apply Settings to All Images"
|
||||
class="bg-gray-700 hover:bg-gray-600 p-1.5 rounded text-xs text-blue-300 transition-colors flex items-center gap-1"
|
||||
>
|
||||
<Copy class="w-3 h-3" /> All
|
||||
@@ -72,10 +83,10 @@ const applyAll = () => {
|
||||
<Palette class="w-4 h-4 text-gray-400" />
|
||||
<input
|
||||
type="color"
|
||||
v-model="store.watermarkSettings.color"
|
||||
v-model="currentColor"
|
||||
class="w-8 h-8 rounded cursor-pointer bg-transparent border-none p-0"
|
||||
/>
|
||||
<span class="text-xs text-gray-300 font-mono">{{ store.watermarkSettings.color }}</span>
|
||||
<span class="text-xs text-gray-300 font-mono">{{ currentColor }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ export interface ImageItem {
|
||||
manualPosition?: { x: number; y: number };
|
||||
scale?: number;
|
||||
opacity?: number;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export interface WatermarkSettings {
|
||||
@@ -55,8 +56,9 @@ export const useGalleryStore = defineStore("gallery", () => {
|
||||
}
|
||||
}
|
||||
|
||||
function setImageSetting(index: number, setting: 'scale' | 'opacity', value: number) {
|
||||
function setImageSetting(index: number, setting: 'scale' | 'opacity' | 'color', value: number | string) {
|
||||
if (images.value[index]) {
|
||||
// @ts-ignore
|
||||
images.value[index][setting] = value;
|
||||
}
|
||||
}
|
||||
@@ -69,16 +71,18 @@ export const useGalleryStore = defineStore("gallery", () => {
|
||||
|
||||
const newScale = current.scale ?? watermarkSettings.value.scale;
|
||||
const newOpacity = current.opacity ?? watermarkSettings.value.opacity;
|
||||
const newColor = current.color ?? watermarkSettings.value.color;
|
||||
|
||||
// 1. Update Global
|
||||
watermarkSettings.value.scale = newScale;
|
||||
watermarkSettings.value.opacity = newOpacity;
|
||||
watermarkSettings.value.color = newColor;
|
||||
|
||||
// 2. Clear overrides for Scale and Opacity on ALL images
|
||||
// (We keep manualPosition because position is usually unique per image content)
|
||||
// 2. Clear overrides on ALL images
|
||||
images.value.forEach(img => {
|
||||
img.scale = undefined;
|
||||
img.opacity = undefined;
|
||||
img.color = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user