diff options
-rw-r--r-- | src/ai_embedders.rs | 6 | ||||
-rw-r--r-- | src/main.rs | 52 |
2 files changed, 45 insertions, 13 deletions
diff --git a/src/ai_embedders.rs b/src/ai_embedders.rs index b30d890..e8e6c8b 100644 --- a/src/ai_embedders.rs +++ b/src/ai_embedders.rs @@ -7,7 +7,7 @@ use crate::{Config, BatchEmbedder, MetricElem}; #[repr(transparent)] #[derive(Serialize, Deserialize)] -pub(crate) struct Imgbedding (Vec<f32>); // TODO das hier zu einem const size slice machen +pub(crate) struct Imgbedding (Vec<f32>); impl MetricElem for Imgbedding { fn dist(&self, other: &Self) -> f64 { self.0.iter().zip(other.0.iter()) @@ -73,10 +73,10 @@ impl BatchEmbedder for ContentEmbedder<'_> { .stdout(Stdio::piped()) .spawn()?; - Ok(BufReader::new(child.stdout.unwrap()) + BufReader::new(child.stdout.unwrap()) .lines() .progress_count(paths.len().try_into().unwrap()) .map(|l| Ok::<_, anyhow::Error>(serde_json::from_str(&l?)?)) - .try_collect()?) + .try_collect() } } diff --git a/src/main.rs b/src/main.rs index 6524de7..1872e31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ use anyhow::Result; use clap::Parser; use priority_queue::PriorityQueue; use sha2::{Sha512_256, Digest}; -use std::{cmp::Ordering, collections::HashMap, fs, io, path::PathBuf}; +use std::{cmp::Ordering, collections::HashMap, fs, io, io::Write, path::PathBuf}; use embedders::*; use pure_embedders::*; @@ -23,9 +23,26 @@ enum Embedder { #[derive(Debug, Parser)] struct Args { - #[arg(short, long, default_value = "hue")] + /// Characteristic to sort by + #[arg(short, long, default_value = "content")] embedder: Embedder, + /// Symlink the sorted images into this directory + #[arg(short = 'o', long)] + symlink_dir: Option<PathBuf>, + + /// Copy the sorted images into this directory. TODO uses COW when available + #[arg(short = 's', long)] + copy_dir: Option<PathBuf>, + + /// Write sorted paths into stdout, one per line + #[arg(short = 'c', long)] + stdout: bool, + + /// Write sorted paths into stdout, null-separated. Overrides -c + #[arg(short = '0', long)] + stdout0: bool, + images: Vec<PathBuf>, } @@ -123,7 +140,7 @@ fn hash_file(p: &PathBuf) -> Result<[u8; 32]> { Ok(hasher.finalize().into_iter().collect::<Vec<u8>>().try_into().unwrap()) } -fn process_embedder<E>(mut e: E, args: Args, cfg: &Config) -> Result<Vec<PathBuf>> +fn process_embedder<E>(mut e: E, args: &Args, cfg: &Config) -> Result<Vec<PathBuf>> where E: BatchEmbedder { if args.images.is_empty() { @@ -169,20 +186,35 @@ fn process_embedder<E>(mut e: E, args: Args, cfg: &Config) -> Result<Vec<PathBuf Ok(tsp_path.iter().map(|i| args.images[*i].clone()).collect()) } +fn symlink_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {todo!()} +fn copy_into(tsp: &[PathBuf], target: &PathBuf) -> Result<()> {todo!()} + fn main() -> Result<()> { let cfg = get_config()?; let args = Args::parse(); let tsp_path = match args.embedder { - Embedder::Brightness => process_embedder(BrightnessEmbedder, args, &cfg), - Embedder::Hue => process_embedder(HueEmbedder, args, &cfg), - Embedder::Color => process_embedder(ColorEmbedder, args, &cfg), - Embedder::Content => process_embedder(ContentEmbedder::new(&cfg), args, &cfg), + Embedder::Brightness => process_embedder(BrightnessEmbedder, &args, &cfg), + Embedder::Hue => process_embedder(HueEmbedder, &args, &cfg), + Embedder::Color => process_embedder(ColorEmbedder, &args, &cfg), + Embedder::Content => process_embedder(ContentEmbedder::new(&cfg), &args, &cfg), }?; - for p in tsp_path { - println!("{:?}", p); - } + args.symlink_dir.into_iter().try_for_each(|p| symlink_into(&tsp_path, &p))?; + args.copy_dir .into_iter().try_for_each(|p| copy_into(&tsp_path, &p))?; + + let path_delim = if args.stdout0 { Some(0) } + else if args.stdout { Some(10) } + else { None }; + + path_delim.into_iter().try_for_each(|delim| { + let mut o = io::BufWriter::new(io::stdout().lock()); + for p in &tsp_path { + o.write(p.as_os_str().to_str().unwrap().as_bytes())?; + o.write(&[delim])?; + } + o.flush() + })?; Ok(()) } |