phase 1 & 2 fix pic scale
This commit is contained in:
@@ -33,147 +33,75 @@ fn scan_dir(path: String) -> Result<Vec<ImageItem>, String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
|
|
||||||
use image::Pixel;
|
use image::Pixel;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(serde::Serialize)]
|
#[derive(serde::Serialize)]
|
||||||
|
|
||||||
struct ZcaResult {
|
struct ZcaResult {
|
||||||
|
|
||||||
x: f64,
|
x: f64,
|
||||||
|
|
||||||
y: f64,
|
y: f64,
|
||||||
|
|
||||||
zone: String,
|
zone: String,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
|
|
||||||
fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
fn get_zca_suggestion(path: String) -> Result<ZcaResult, String> {
|
||||||
|
|
||||||
let img = image::open(&path).map_err(|e| e.to_string())?;
|
let img = image::open(&path).map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
let (width, height) = img.dimensions();
|
let (width, height) = img.dimensions();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let bottom_start_y = (height as f64 * 0.8) as u32;
|
let bottom_start_y = (height as f64 * 0.8) as u32;
|
||||||
|
|
||||||
let zone_height = height - bottom_start_y;
|
let zone_height = height - bottom_start_y;
|
||||||
|
|
||||||
let zone_width = width / 3;
|
let zone_width = width / 3;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let zones = [
|
let zones = [
|
||||||
|
|
||||||
("Left", 0, bottom_start_y),
|
("Left", 0, bottom_start_y),
|
||||||
|
|
||||||
("Center", zone_width, bottom_start_y),
|
("Center", zone_width, bottom_start_y),
|
||||||
|
|
||||||
("Right", zone_width * 2, bottom_start_y),
|
("Right", zone_width * 2, bottom_start_y),
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mut min_std_dev = f64::MAX;
|
let mut min_std_dev = f64::MAX;
|
||||||
|
|
||||||
let mut best_zone = "Center";
|
let mut best_zone = "Center";
|
||||||
|
|
||||||
let mut best_pos = (0.5, 0.9); // Default center
|
let mut best_pos = (0.5, 0.9); // Default center
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (name, start_x, start_y) in zones.iter() {
|
for (name, start_x, start_y) in zones.iter() {
|
||||||
|
|
||||||
let mut luma_values = Vec::with_capacity((zone_width * zone_height) as usize);
|
let mut luma_values = Vec::with_capacity((zone_width * zone_height) as usize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for y in *start_y..height {
|
for y in *start_y..height {
|
||||||
|
|
||||||
for x in *start_x..(*start_x + zone_width) {
|
for x in *start_x..(*start_x + zone_width) {
|
||||||
|
|
||||||
if x >= width { continue; }
|
if x >= width { continue; }
|
||||||
|
|
||||||
let pixel = img.get_pixel(x, y);
|
let pixel = img.get_pixel(x, y);
|
||||||
|
|
||||||
let rgb = pixel.to_rgb();
|
let rgb = pixel.to_rgb();
|
||||||
|
|
||||||
let luma = 0.299 * rgb[0] as f64 + 0.587 * rgb[1] as f64 + 0.114 * rgb[2] as f64;
|
let luma = 0.299 * rgb[0] as f64 + 0.587 * rgb[1] as f64 + 0.114 * rgb[2] as f64;
|
||||||
|
|
||||||
luma_values.push(luma);
|
luma_values.push(luma);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let count = luma_values.len() as f64;
|
let count = luma_values.len() as f64;
|
||||||
|
|
||||||
if count == 0.0 { continue; }
|
if count == 0.0 { continue; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let mean = luma_values.iter().sum::<f64>() / count;
|
let mean = luma_values.iter().sum::<f64>() / count;
|
||||||
|
|
||||||
let variance = luma_values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / count;
|
let variance = luma_values.iter().map(|v| (v - mean).powi(2)).sum::<f64>() / count;
|
||||||
|
|
||||||
let std_dev = variance.sqrt();
|
let std_dev = variance.sqrt();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if std_dev < min_std_dev {
|
if std_dev < min_std_dev {
|
||||||
|
|
||||||
min_std_dev = std_dev;
|
min_std_dev = std_dev;
|
||||||
|
|
||||||
best_zone = name;
|
best_zone = name;
|
||||||
|
|
||||||
let center_x_px = *start_x as f64 + (zone_width as f64 / 2.0);
|
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%)
|
||||||
let center_y_px = *start_y as f64 + (zone_height as f64 / 2.0);
|
// 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);
|
best_pos = (center_x_px / width as f64, center_y_px / height as f64);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Ok(ZcaResult {
|
Ok(ZcaResult {
|
||||||
|
|
||||||
x: best_pos.0,
|
x: best_pos.0,
|
||||||
|
|
||||||
y: best_pos.1,
|
y: best_pos.1,
|
||||||
|
|
||||||
zone: best_zone.to_string(),
|
zone: best_zone.to_string(),
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
|
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
|
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.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])
|
||||||
|
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
|
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,11 +6,12 @@ const store = useGalleryStore();
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="w-full h-full flex items-center justify-center bg-black relative">
|
<div class="w-full h-full flex items-center justify-center bg-black relative p-4 overflow-hidden">
|
||||||
<div v-if="store.selectedImage" class="relative max-w-full max-h-full">
|
<div v-if="store.selectedImage" class="relative inline-flex justify-center items-center" style="max-width: 100%; max-height: 100%;">
|
||||||
<img
|
<img
|
||||||
:src="convertFileSrc(store.selectedImage.path)"
|
:src="convertFileSrc(store.selectedImage.path)"
|
||||||
class="max-w-full max-h-full object-contain"
|
class="max-w-full max-h-full w-auto h-auto block shadow-lg"
|
||||||
|
style="max-height: calc(100vh - 10rem);"
|
||||||
alt="Hero Image"
|
alt="Hero Image"
|
||||||
/>
|
/>
|
||||||
<!-- Watermark Overlay Placeholder -->
|
<!-- Watermark Overlay Placeholder -->
|
||||||
|
|||||||
Reference in New Issue
Block a user