seperate color

This commit is contained in:
Julian Freeman
2026-01-19 00:53:11 -04:00
parent fd90ac1df3
commit 358aae92dc
5 changed files with 31 additions and 12 deletions

View File

@@ -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]);

View File

@@ -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

View File

@@ -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',

View File

@@ -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>

View File

@@ -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;
});
}