diff --git a/Cargo.lock b/Cargo.lock index b1b58e8..66a23d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,6 +144,46 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clap" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.64", +] + +[[package]] +name = "clap_lex" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" + [[package]] name = "color_quant" version = "1.1.0" @@ -384,6 +424,12 @@ dependencies = [ "crunchy", ] +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -424,6 +470,7 @@ version = "0.1.0" dependencies = [ "base64 0.22.1", "bktree", + "clap", "env_logger", "image", "log", @@ -685,7 +732,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", ] [[package]] @@ -702,18 +749,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -887,6 +934,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "syn" version = "1.0.103" @@ -898,6 +951,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn" +version = "2.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ad3dee41f36859875573074334c200d1add8e4a87bb37113ebd31d926b7b11f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "tempfile" version = "3.10.1" @@ -994,7 +1058,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-shared", ] @@ -1016,7 +1080,7 @@ checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.103", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/Cargo.toml b/Cargo.toml index 4375ae2..9d7e515 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,4 @@ log = "0.4.21" env_logger = "0.11.3" bktree = "1.0.1" viuer = "0.7.1" +clap = { version = "4.5.4", features = ["derive"] } diff --git a/src/bin/dct.rs b/src/bin/dct.rs new file mode 100644 index 0000000..266f324 --- /dev/null +++ b/src/bin/dct.rs @@ -0,0 +1,66 @@ +use std::env; +use std::f64::consts::{PI, SQRT_2}; +use image::{save_buffer, GenericImageView, GrayImage}; + +fn dct(img: &image::DynamicImage) -> GrayImage { + //let mut dct_values: = [0.0; img.width() * img.height()]; + let w = img.width(); + let h = img.height(); + let mut dct_img = GrayImage::new(w, h); + + //let mut dct_values: Vec = Vec::new(); + for u in 0..w { + for v in 0..h { + let w = w as f64; + let h = h as f64; + //let k = (v*img.width())+u; + let mut alpha = 0.25; + if u == 0 { + alpha = alpha / SQRT_2 + } + if v == 0 { + alpha = alpha / SQRT_2 + } + let v: f64 = v as f64; + let u: f64 = u as f64; + let mut sum: f64 = 0.0; + for (x, y, pix) in img.pixels() { + let x: f64 = x as f64; + let y: f64 = y as f64; + let pixel = pix[0] as f64; + // sum += + // pixel * + // (x*u*PI/16.0).cos() * + // (y*v*PI/16.0).cos() + sum += + pixel * + ( + PI/w* + (x+0.5)*u + ).cos() + * + ( + PI/h* + (y+0.5)*v + ).cos() + } + //dct_values[k] = alpha * sum; + //dct_values.push(alpha * sum); + print!("{sum}\t"); + //sum = (sum + 200000.0)/784.0; + print!("{}\n", sum * alpha); + let pixel = (sum).abs() as u8; + println!("{u}, {v}:\t {sum}"); + dct_img.put_pixel(u as u32, v as u32, image::Luma([pixel])); + } + } + dct_img +} + +fn main() { + let args: Vec = env::args().collect(); + let path = args[1].clone(); + let img = image::open(&path).unwrap(); + let dct = dct(&img); + dct.save("dct.png").unwrap(); +} \ No newline at end of file diff --git a/src/bin/dctfilename.rs b/src/bin/dctfilename.rs index 0641c45..b81c50e 100644 --- a/src/bin/dctfilename.rs +++ b/src/bin/dctfilename.rs @@ -1,34 +1,22 @@ //use image_similarity::descriptors::dct::DCT; use image_similarity::descriptors::{DCT, Descriptor}; -use std::env; +use std::path::PathBuf; use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _}; use log::debug; +use clap::Parser; +#[derive(Parser)] +#[command(version, about, long_about = None)] struct Cfg { - path: String -} - -impl Cfg{ - fn load(args: &[String]) -> Result { - if args.len() < 2 { - return Err("Filename argument required"); - } - let path = args[1].clone(); - Ok(Cfg { path }) - } + path: PathBuf } fn main() { env_logger::init(); + let cfg = Cfg::parse(); - //Init all descriptors: let desc = DCT::new().with_quality(50); - let args: Vec = env::args().collect(); - - let cfg = Cfg::load(&args) - .expect("Error loading config"); - let img = image::open(cfg.path) .expect("Unable to open file"); let phash: u64 = desc.describe(&img); diff --git a/src/bin/dctquery.rs b/src/bin/dctquery.rs index 4a998e1..d8a74f8 100644 --- a/src/bin/dctquery.rs +++ b/src/bin/dctquery.rs @@ -3,7 +3,6 @@ use image_similarity::descriptors::{DCT, Descriptor}; use image_similarity::store::DescriptorStore; use std::env; use log::{info, debug, error}; -use viuer::{Config, print}; struct Cfg { path: String diff --git a/src/main.rs b/src/main.rs index 09d360b..5b6f311 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,59 @@ use image_similarity::store::DescriptorStore; -use image_similarity::descriptors::DCT; +use image_similarity::descriptors::{Descriptor, DCT}; use log::info; +use std::path::PathBuf; +use std::thread; +use clap::Parser; -fn main() { - env_logger::init(); +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Cfg { + /// Path that contains the input images. Will not traverse directories. + path: PathBuf +} + +fn make_store(descriptor: T, input_path: PathBuf, save_path: PathBuf) -> () { let mut store = DescriptorStore::new() - .with_file("store.messagepack"); + .with_file(save_path); info!("{}", store); - let desc = - DCT::new() - .with_quality(30); - store.insert_directory("data", desc); + store.insert_directory(input_path, descriptor); info!("{}", store); store.save().expect("Error saving"); } + +fn main() { + env_logger::init(); + let cfg = Cfg::parse(); + + let mut threads = vec![]; + + let dct_50 = + DCT::new() + .with_quality(50); + let dct_30 = + DCT::new() + .with_quality(30); + let dct_10 = + DCT::new() + .with_quality(10); + + threads.push( + thread::spawn(move || { + make_store(dct_50, "data".into(), "dct50.messagepack".into()); + }) + ); + threads.push( + thread::spawn(move || { + make_store(dct_30, "data".into(), "dct30.messagepack".into()); + }) + ); + threads.push( + thread::spawn(move || { + make_store(dct_10, "data".into(), "dct10.messagepack".into()); + }) + ); + for thread in threads { + let _ = thread.join(); + } +} diff --git a/src/store.rs b/src/store.rs index d13840a..c5c7ef9 100644 --- a/src/store.rs +++ b/src/store.rs @@ -8,7 +8,6 @@ use std::path::Path; use std::fmt; use log::{info, debug, error}; use bktree::*; -use viuer::{Config, print}; #[derive(Debug)] pub enum SaveError { @@ -66,6 +65,7 @@ impl DescriptorStore { /// Inserts a single value into the store pub fn insert(&mut self, key: u64, value: String) { self.map.insert(key, value); + self.bktree.insert(key); } /// Calculates all descriptions with a given descriptor @@ -112,7 +112,7 @@ impl DescriptorStore { match name { Some(n) => { println!("{element:b}: {n} (distance: {distance})"); - if x+16 >= term_width { + if x+16 >= term_width { x = 0; y += 8; }