diff --git a/Cargo.lock b/Cargo.lock index 26d2ac8..a01d6a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,15 +32,6 @@ dependencies = [ "libc", ] -[[package]] -name = "ansi_colours" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1558bd2075d341b9ca698ec8eb6fcc55a746b1fc4255585aad5b141d918a80" -dependencies = [ - "rgb", -] - [[package]] name = "anstream" version = "0.6.14" @@ -77,7 +68,7 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a64c907d4e79225ac72e2a354c9ce84d50ebb4586dee56c82b3ee73004f537f5" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -87,7 +78,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -96,12 +87,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -176,7 +161,7 @@ dependencies = [ "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets", ] [[package]] @@ -232,15 +217,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] -name = "console" -version = "0.15.8" +name = "console_error_panic_hook" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "windows-sys 0.52.0", + "cfg-if", + "wasm-bindgen", ] [[package]] @@ -347,31 +330,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossterm" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" -dependencies = [ - "bitflags 2.5.0", - "crossterm_winapi", - "libc", - "mio", - "parking_lot", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - [[package]] name = "crunchy" version = "0.2.2" @@ -436,12 +394,6 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - [[package]] name = "env_filter" version = "0.1.0" @@ -465,16 +417,6 @@ dependencies = [ "log", ] -[[package]] -name = "errno" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "exr" version = "1.5.2" @@ -490,12 +432,6 @@ dependencies = [ "threadpool", ] -[[package]] -name = "fastrand" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" - [[package]] name = "flate2" version = "1.0.24" @@ -709,16 +645,17 @@ dependencies = [ name = "image_similarity" version = "0.1.0" dependencies = [ - "base64 0.22.1", + "base64", "bktree", "clap", + "console_error_panic_hook", "env_logger", "image", "log", "plotters", "rmp-serde", "serde", - "viuer", + "wasm-bindgen", ] [[package]] @@ -770,7 +707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets", ] [[package]] @@ -783,12 +720,6 @@ dependencies = [ "libc", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" - [[package]] name = "lock_api" version = "0.4.9" @@ -838,18 +769,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - [[package]] name = "nanorand" version = "0.7.0" @@ -948,29 +867,6 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" -[[package]] -name = "parking_lot" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.52.5", -] - [[package]] name = "paste" version = "1.0.9" @@ -1122,15 +1018,6 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "redox_syscall" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" -dependencies = [ - "bitflags 2.5.0", -] - [[package]] name = "redox_users" version = "0.4.5" @@ -1171,15 +1058,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" -[[package]] -name = "rgb" -version = "0.8.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" -dependencies = [ - "bytemuck", -] - [[package]] name = "rmp" version = "0.8.11" @@ -1211,19 +1089,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" -dependencies = [ - "bitflags 2.5.0", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - [[package]] name = "same-file" version = "1.0.6" @@ -1257,36 +1122,6 @@ version = "1.0.147" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "smallvec" version = "1.10.0" @@ -1330,27 +1165,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.61" @@ -1409,22 +1223,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" -[[package]] -name = "viuer" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec2ede5c8814363f92f862892dfe71a266f6816b649ca435aed1ff5e2cf3454e" -dependencies = [ - "ansi_colours", - "base64 0.21.7", - "console", - "crossterm", - "image", - "lazy_static", - "tempfile", - "termcolor", -] - [[package]] name = "walkdir" version = "2.5.0" @@ -1533,7 +1331,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -1548,16 +1346,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", + "windows-targets", ] [[package]] @@ -1566,22 +1355,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] @@ -1590,46 +1364,28 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - [[package]] name = "windows_aarch64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - [[package]] name = "windows_i686_gnu" version = "0.52.5" @@ -1642,48 +1398,24 @@ version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - [[package]] name = "windows_i686_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - [[package]] name = "windows_x86_64_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - [[package]] name = "windows_x86_64_msvc" version = "0.52.5" diff --git a/Cargo.toml b/Cargo.toml index a5ba1b3..2f3e057 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,10 @@ base64 = "0.22.1" log = "0.4.21" env_logger = "0.11.3" bktree = "1.0.1" -viuer = "0.7.1" clap = { version = "4.5.4", features = ["derive"] } plotters = "0.3.6" +wasm-bindgen = "0.2.92" +console_error_panic_hook = "0.1.7" + +[lib] +crate-type = ["cdylib", "rlib"] diff --git a/src/bin/dctfilename.rs b/src/bin/dctfilename.rs index 1d6cdec..a76f56d 100644 --- a/src/bin/dctfilename.rs +++ b/src/bin/dctfilename.rs @@ -23,5 +23,5 @@ fn main() { debug!("Phash integer:\n{phash}"); debug!("Phash binary:\n{phash:064b}"); let output = URL_SAFE_NO_PAD.encode(phash.to_be_bytes()); - println!("{output}") + println!("{output}"); } diff --git a/src/bin/dctquery.rs b/src/bin/dctquery.rs index 7915382..ecac929 100644 --- a/src/bin/dctquery.rs +++ b/src/bin/dctquery.rs @@ -24,17 +24,11 @@ fn main() { let img = image::open(cfg.path) .expect("Unable to open file"); - // let conf = viuer::Config { - // width: Some(16), - // height: Some(8), - // ..Default::default() - // }; - // viuer::print(&img, &conf).expect("Image printing failed."); + let phash: u64 = desc.describe(&img); - let store = + let _store = DescriptorStore::new(Box::new(desc)) .with_file("dct50.messagepack"); info!("Phash integer:\n{phash}"); info!("Phash binary:\n{phash:064b}"); - store.print_nn(phash, cfg.distance, cfg.show_images); } \ No newline at end of file diff --git a/src/bin/experiment.rs b/src/bin/experiment.rs deleted file mode 100644 index ab2a847..0000000 --- a/src/bin/experiment.rs +++ /dev/null @@ -1,36 +0,0 @@ -use image_similarity::descriptors::{Descriptor, DCT}; -use std::collections::HashMap; -use std::fs; - -fn main() { - env_logger::init(); - - let desc = DCT::new(); - - //Initialize hashmap, empty or from cached file: - let count = fs::read_dir("img").unwrap().count(); - let map_file = fs::read("map.messagepack"); - let mut map: HashMap = match map_file { - Ok(f) => rmp_serde::from_slice(&f).unwrap(), - Err(_e) => HashMap::with_capacity(count), - }; - - //Calculate phashes for all images - for node in fs::read_dir("img").unwrap() { - let file = node.expect("Error walking directory"); - let name = file.file_name().into_string().expect("Issue with filename"); - if !map.contains_key(&name) { - let img = image::open(file.path()).expect("Unable to open file"); - let phash = desc.describe(&img); - map.insert(name, phash); - } - } - - for (key, val) in map.iter() { - println!("{key: >15}: {val}\t {val:b}"); - } - - //Serialize hashmap with MessagePack: - let _serialized: Vec = rmp_serde::to_vec(&map).unwrap(); - //fs::write("map.messagepack",&serialized).unwrap(); -} diff --git a/src/bin/mutate.rs b/src/bin/mutate.rs index 350c971..1774d4c 100644 --- a/src/bin/mutate.rs +++ b/src/bin/mutate.rs @@ -16,23 +16,15 @@ fn main() { let cfg = Cfg::parse(); - let img = image::open(&cfg.path) + let img = image::open(cfg.path) .expect("Unable to open file"); let mutators = get_all_mutators(); - let conf = viuer::Config { - width: Some(16), - height: Some(8), - ..Default::default() - }; for mutator in mutators { let mutated = mutator.mutate(&img); - let filename = "mut".to_string() + &mutator.tag() + &"png".to_string(); - println!("Saving to {}", filename); + let filename = "mut".to_string() + &mutator.tag() + "png"; + println!("Saving to {filename}"); mutated.save(filename).expect("Saving image failed"); - if cfg.show_images { - viuer::print(&mutated, &conf).expect("Image printing failed."); - } } } \ No newline at end of file diff --git a/src/descriptors/dct.rs b/src/descriptors/dct.rs index 50dcd3d..3d5e06d 100644 --- a/src/descriptors/dct.rs +++ b/src/descriptors/dct.rs @@ -29,10 +29,11 @@ impl DCT { 50..=100 => 200.0 - 2.0*quality as f32, _ => 100.0 // Invalid input: set to base quality }; - for i in 0..64 { - quantization_matrix[i] = ((scalar * self.quantization_matrix[i] as f32 + 50.0) / 100.0).floor() as u8; - if quantization_matrix[i] == 0 { - quantization_matrix[i] = 1; + //for i in 0..64 { + for (_, cell) in quantization_matrix.iter_mut().enumerate() { + *cell = ((scalar * *cell as f32 + 50.0) / 100.0).floor() as u8; + if *cell == 0 { + *cell = 1; } } self.quantization_matrix = quantization_matrix; @@ -40,17 +41,17 @@ impl DCT { } /// - fn dct(&self, img: &image::DynamicImage) -> [f64; 64] { + pub fn dct(&self, img: &image::DynamicImage) -> [f64; 64] { let mut dct_values: [f64; 64] = [0.0; 64]; for u in 0..8 { for v in 0..8 { let k = (v*8)+u; let mut alpha = 0.25; if u == 0 { - alpha = alpha / SQRT_2 + alpha /= SQRT_2 } if v == 0 { - alpha = alpha / SQRT_2 + alpha /= SQRT_2 } let v: f64 = v as f64; let u: f64 = u as f64; @@ -72,7 +73,8 @@ impl DCT { fn idct(&self, dct_values: [f64; 64]) -> [u8; 64] { let mut reconstructed: [u8; 64] = [0; 64]; - for k in 0..64 { + //for k in 0..64 { + for (k, item) in reconstructed.iter_mut().enumerate() { let x = (k%8) as f64; let y = (k/8) as f64; let mut sum = 0.0; @@ -80,10 +82,10 @@ impl DCT { for v in 0..8 { let mut alpha = 1.0; if u == 0 { - alpha = alpha / SQRT_2 + alpha /= SQRT_2 } if v == 0 { - alpha = alpha / SQRT_2 + alpha /= SQRT_2 } let uv = (v*8)+u; let v = v as f64; @@ -96,12 +98,18 @@ impl DCT { } } sum = 127.0 + (0.25 * sum).round(); - reconstructed[k] = std::cmp::min(255_u8, sum as u8); + *item = std::cmp::min(255_u8, sum as u8); } reconstructed } } +impl Default for DCT { + fn default() -> Self { + Self::new() + } +} + impl Descriptor for DCT { fn info(&self) -> String { "dct".to_string() @@ -124,7 +132,7 @@ impl Descriptor for DCT { if log_enabled!(Level::Debug) { resized.save("resize.png").expect("Error saving file"); // De-quantization: - let mut dequant = dct_values.clone(); + let mut dequant = dct_values; for i in 0..64 { dequant[i] = dct_values[i] * self.quantization_matrix[i] as f64; } @@ -189,8 +197,8 @@ impl Descriptor for DCT { } // Shift masks - sign_mask = sign_mask << 1; - pearson_mask = pearson_mask << 1; + sign_mask <<= 1; + pearson_mask <<= 1; debug!("Sign mask: {:028b}", sign_mask); debug!("Pearson mask: {:028b}", pearson_mask); } @@ -199,11 +207,11 @@ impl Descriptor for DCT { let mut mask = sign_mask; debug!("Mask: {:064b}", mask); - mask = mask << 28; + mask <<= 28; debug!("Mask: {:064b}", mask); mask += pearson_mask; debug!("Mask: {:064b}", mask); - mask = mask << 8; + mask <<= 8; debug!("Mask: {:064b}", mask); // TODO: Do something with these last 8 bits. mask diff --git a/src/descriptors/mod.rs b/src/descriptors/mod.rs index 5e0e747..0fd53d9 100644 --- a/src/descriptors/mod.rs +++ b/src/descriptors/mod.rs @@ -55,10 +55,8 @@ impl Descriptor for Median { fn describe(&self, img: &image::DynamicImage) -> u64 { let img = self.resize(img); let mut values: [u8; 64] = [0; 64]; - let mut i: usize = 0; - for (_, _, pix) in img.pixels() { + for (i, (_, _, pix)) in img.pixels().enumerate() { values[i] = pix[0]; - i = i+1; } let median = median64(&values); let mut mask: u64 = 0; @@ -67,15 +65,16 @@ impl Descriptor for Median { if pix[0] > median { mask += 1; } - mask = mask << 1; + mask <<= 1; } mask } } pub fn get_all_descriptors() -> Vec> { - let mut descriptors: Vec> = Vec::with_capacity(2); - descriptors.push(Box::new(DCT::new())); - descriptors.push(Box::new(Median)); + let descriptors: Vec> = + vec![Box::new(DCT::new()), Box::new(Median)]; + // descriptors.push(Box::new(DCT::new())); + // descriptors.push(Box::new(Median)); descriptors } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index dbce76e..69f07ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,4 +4,5 @@ //! If two images are (almost) the same, their descriptions will be the same. pub mod descriptors; pub mod store; -pub mod mutators; \ No newline at end of file +pub mod mutators; +pub mod wasm; \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index f14a840..0b2491a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,6 @@ fn main() { } for node in fs::read_dir(cfg.path).unwrap() { - //println!("{:?}", node); let file = node.expect("Error walking directory"); let name = match file.file_name().into_string() { Ok(v) => v, @@ -54,7 +53,7 @@ fn main() { error!("Failed to process {}: {}", name, e); continue } - }; + }.thumbnail_exact(8, 8); //Store the phashes of the base image for store in &mut stores { @@ -72,7 +71,7 @@ fn main() { } for store in &stores { store.save().expect("Error saving store"); - println!("{}", store); + println!("{store}"); } // Create PR-curve graphs from stores @@ -96,18 +95,17 @@ fn main() { .disable_mesh() .x_desc("Recall") .y_desc("Precision") - .x_label_formatter(&|x| format!("{:.3}", x)) - .y_label_formatter(&|x| format!("{:.3}", x)) + .x_label_formatter(&|x| format!("{x:.3}")) + .y_label_formatter(&|x| format!("{x:.3}")) .draw().unwrap(); let colors = [&RED, &BLUE, &CYAN, &MAGENTA, &BLACK, &GREEN, &YELLOW]; let n = colors.len(); - let mut i = 0; - for mutator_stats in stats { + for (i, mutator_stats) in stats.into_iter().enumerate() { // And we can draw something in the drawing area let pr_curve = mutator_stats.pr_curve(max_threshold); println!("{}:", mutator_stats.name); for (x, y) in pr_curve.clone() { - println!("{}, {}", x, y); + println!("{x}, {y}"); } let color = colors[i % n]; chart.draw_series(LineSeries::new( @@ -116,17 +114,11 @@ fn main() { ).point_size(2)).unwrap() .label(mutator_stats.name) .legend(move |(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], color)); - i += 1; } - //chart.configure_series_labels().border_style(BLACK).draw().unwrap(); chart.configure_series_labels() .position(SeriesLabelPosition::MiddleLeft) - //.legend_area_size(5) .border_style(BLACK) - //.background_style(BLUE.mix(0.1)) - //.label_font(("Calibri", 20)) .draw() .unwrap(); - //println!("{}", store); } } diff --git a/src/mutators/mod.rs b/src/mutators/mod.rs index d51ba37..fbc3247 100644 --- a/src/mutators/mod.rs +++ b/src/mutators/mod.rs @@ -72,10 +72,12 @@ impl Mutator for Blur { } pub fn get_all_mutators() -> Vec> { - let mut mutators: Vec> = Vec::with_capacity(4); - mutators.push(Box::new(Flip)); - mutators.push(Box::new(Hue)); - mutators.push(Box::new(Sharp)); - mutators.push(Box::new(Blur)); + let mutators: Vec> = //Vec::with_capacity(4); + vec![ + Box::new(Flip), + Box::new(Hue), + Box::new(Sharp), + Box::new(Blur), + ]; mutators } \ No newline at end of file diff --git a/src/store.rs b/src/store.rs index 87a1197..ac469ed 100644 --- a/src/store.rs +++ b/src/store.rs @@ -34,8 +34,7 @@ impl PRStats { }; let tpos = self.true_positives[t] as f64; let fpos = self.false_positives[t] as f64; - let p = tpos / (tpos + fpos); - p + tpos / (tpos + fpos) } pub fn recall(&self, threshold: usize) -> f64 { let t = match threshold { @@ -44,8 +43,7 @@ impl PRStats { }; let tpos = self.true_positives[t] as f64; let fneg = self.false_negatives[t] as f64; - let r = tpos / (tpos + fneg); - r + tpos / (tpos + fneg) } pub fn pr(&self, threshold: usize) -> (f64, f64) { let t = match threshold { @@ -87,7 +85,7 @@ pub struct DescriptorStore { } impl DescriptorStore { - /// Makes a new empty DescriptorStore with default settings + /// Makes a new empty `DescriptorStore` with default settings pub fn new(descriptor: Box) -> Self { let map: HashMap> = HashMap::new(); //let seen: HashSet = HashSet::new(); @@ -105,23 +103,22 @@ impl DescriptorStore { pub fn with_file>(mut self, path: P) -> Self { self.save_location = std::path::PathBuf::from(path.as_ref()); let map_file = fs::read(&self.save_location); - match map_file { - Ok(f) => { - self.map = rmp_serde::from_slice(&f).unwrap(); - for i in self.map.keys() { - self.bktree.insert(*i); - } - let mut seen: HashSet = HashSet::new(); - for bucket in self.map.values() { - for element in bucket { - if !element.starts_with("mut.") { - seen.insert(element.clone()); - } + if let Ok(f) = map_file { + self.map = rmp_serde::from_slice(&f).unwrap(); + for i in self.map.keys() { + self.bktree.insert(*i); + } + let mut seen: HashSet = HashSet::new(); + for bucket in self.map.values() { + for element in bucket { + if !element.starts_with("mut.") { + seen.insert(element.clone()); } } - self.seen = Some(seen); - }, - Err(_) => info!("{} not found, starting from empty store.", self.save_location.display()), + } + self.seen = Some(seen); + } else { + info!("{} not found, starting from empty store.", self.save_location.display()); }; self } @@ -147,8 +144,8 @@ impl DescriptorStore { Ok(value) => value, Err(_e) => return Err(SaveError::Serialization), }; - match fs::write(&self.save_location, &serialized) { - Ok(_) => Ok(()), + match fs::write(&self.save_location, serialized) { + Ok(()) => Ok(()), Err(_e) => Err(SaveError::File), } } @@ -167,7 +164,7 @@ impl DescriptorStore { }, None => { for bucket in self.map.values() { - if bucket.contains(&value) { + if bucket.contains(value) { return true; } } @@ -178,7 +175,7 @@ impl DescriptorStore { pub fn get(&self, value: &String) -> Option { for (key, bucket) in self.map.iter() { - if bucket.contains(&value) { + if bucket.contains(value) { return Some(*key); } } @@ -187,7 +184,7 @@ impl DescriptorStore { /// Inserts a single value into the store pub fn insert(&mut self, key: &u64, value: String) { - let bucket = match self.map.get(&key) { + let bucket = match self.map.get(key) { Some(b) => { let mut n = b.clone(); if !n.contains(&value) { @@ -213,7 +210,9 @@ impl DescriptorStore { continue } }; - if !self.has_value(&name) { // !self.contains(name.to_string()) { + if !self.has_value(&name) { + debug!("{} already known, skipping.", name); + } else { info!("Processing {}", name); let img = match image::open(file.path()) { Ok(v) => v, @@ -227,8 +226,6 @@ impl DescriptorStore { println!("{} duplicate of {:?}", name, self.map.get(&phash)); } self.insert(&phash, name); - } else { - debug!("{} already known, skipping.", name); } self.save().expect("error"); } @@ -238,15 +235,15 @@ impl DescriptorStore { pub fn store(&mut self, img: &DynamicImage, name: String) { if !self.has_value(&name) { - let phash = self.descriptor.describe(&img); + let phash = self.descriptor.describe(img); self.insert(&phash, name); } } /// Nearest neighbours pub fn nn(&self, from: u64, max_distance: usize) -> Vec<(&u64, isize)> { - let mut neighbours = self.bktree.find(from, max_distance.try_into().unwrap()); - neighbours.sort_by(|a, b| a.1.cmp(&b.1)); + let neighbours = self.bktree.find(from, max_distance.try_into().unwrap()); + //neighbours.sort_by(|a, b| a.1.cmp(&b.1)); neighbours } @@ -263,44 +260,6 @@ impl DescriptorStore { results } - pub fn print_nn(&self, from: u64, max_distance: usize, show_images: bool) { - //println!("{from:064b}"); - let neighbours = self.nn(from, max_distance); - let (term_width, _) = viuer::terminal_size(); - let mut x = 0; - let mut y = 8; - for (element, distance) in neighbours { - let elements = self.map.get(element); - match elements { - Some(paths) => { - for path in paths { - println!("{element:064b}: {:?} (distance: {distance})", path); - if show_images { - if x+16 >= term_width { - x = 0; - y += 8; - } - let conf = viuer::Config { - width: Some(16), - height: Some(8), - x, - y, - use_kitty: false, - ..Default::default() - }; - x += 16; - let path = "data/".to_string() + path; - let img = image::open(&path).unwrap(); - let img = img.grayscale().thumbnail_exact(8, 8); - viuer::print(&img, &conf).expect("Image printing failed."); - } - } - }, - None => () - }; - } - } - pub fn print_most_dups(&self) { let mut most = 0; for bucket in self.map.values() { @@ -319,7 +278,7 @@ impl DescriptorStore { let value_entry = format!("{value}\n"); output.push_str(&value_entry); } - output.push_str("\n"); + output.push('\n'); } } print!("DescriptorStore:\n{}Total: {}", output, self.map.len()) @@ -415,7 +374,7 @@ impl fmt::Display for DescriptorStore { let value_entry = format!("\t{value}\n"); output.push_str(&value_entry); } - output.push_str("\n"); + output.push('\n'); } write!(f, "DescriptorStore:\n{}Total: {}", output, self.map.len()) }