diff --git a/src/cache.rs b/src/cache.rs index 7617e34..d19bbfe 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -8,20 +8,22 @@ extern crate image; extern crate num; extern crate sha1; -use self::flate2::Compression; -use self::flate2::read::ZlibDecoder; -use self::flate2::write::ZlibEncoder; -use self::image::DynamicImage; -use self::sha1::Sha1; use std::default::Default; -use std::fs::{create_dir_all, File, remove_dir_all}; +use std::fs::{create_dir_all, remove_dir_all, File}; use std::io::{Error, ErrorKind, Read, Write}; use std::option::Option; use std::path::Path; use std::result::Result; use std::str::FromStr; + use super::rustc_serialize::json; +use self::flate2::read::ZlibDecoder; +use self::flate2::write::ZlibEncoder; +use self::flate2::Compression; +use self::image::DynamicImage; +use self::sha1::Sha1; + pub const DEFAULT_CACHE_DIR: &'static str = "./.hash_cache"; const CACHED_IMAGE_EXT: &'static str = "png"; const CACHED_MATRIX_EXT: &'static str = "dft"; @@ -36,7 +38,9 @@ struct CacheMetadata { impl Default for CacheMetadata { fn default() -> CacheMetadata { - CacheMetadata { cache_version: CACHE_VERSION } + CacheMetadata { + cache_version: CACHE_VERSION, + } } } @@ -94,12 +98,10 @@ impl<'a> Cache<'a> { if current_metadata != loaded_metadata { // If they don't wipe the cache to start new match remove_dir_all(self.cache_dir) { - Ok(_) => { - match create_dir_all(self.cache_dir) { - Ok(_) => (), - Err(e) => println!("Error: {}", e), - } - } + Ok(_) => match create_dir_all(self.cache_dir) { + Ok(_) => (), + Err(e) => println!("Error: {}", e), + }, Err(e) => println!("Error: {}", e), }; }; @@ -148,22 +150,26 @@ impl<'a> Cache<'a> { /** * Put an image buffer in the cache */ - pub fn put_image_in_cache(&self, - path: &Path, - size: u32, - image: &DynamicImage) - -> Result { + pub fn put_image_in_cache( + &self, + path: &Path, + size: u32, + image: &DynamicImage, + ) -> Result { let hash = self.get_file_hash(&path); match hash { Ok(sha1) => { - let cache_path_str = format!("{}/image/{}x{}/{}/{}.{}", - self.cache_dir, - size, - size, - &sha1[..10], - sha1, - CACHED_IMAGE_EXT); - let cache_dir_str = format!("{}/image/{}x{}/{}", self.cache_dir, size, size, &sha1[..10]); + let cache_path_str = format!( + "{}/image/{}x{}/{}/{}.{}", + self.cache_dir, + size, + size, + &sha1[..10], + sha1, + CACHED_IMAGE_EXT + ); + let cache_dir_str = + format!("{}/image/{}x{}/{}", self.cache_dir, size, size, &sha1[..10]); // println!("Saving: {}", cache_path_str); match create_dir_all(cache_dir_str) { Ok(_) => { @@ -196,22 +202,21 @@ impl<'a> Cache<'a> { /** * Get an image buffer out of the cache */ - pub fn get_image_from_cache(&self, - path: &Path, - size: u32) - -> Option { + pub fn get_image_from_cache(&self, path: &Path, size: u32) -> Option { if self.use_cache { let hash = self.get_file_hash(&path); match hash { Ok(sha1) => { // Check if the file exists in the cache - let cache_path_str = format!("{}/image/{}x{}/{}/{}.{}", - self.cache_dir, - size, - size, - &sha1[..10], - sha1, - CACHED_IMAGE_EXT); + let cache_path_str = format!( + "{}/image/{}x{}/{}/{}.{}", + self.cache_dir, + size, + size, + &sha1[..10], + sha1, + CACHED_IMAGE_EXT + ); let cached_path = Path::new(&cache_path_str); // Try to open, if it does, then we can read the image in match File::open(&cached_path) { @@ -237,35 +242,44 @@ impl<'a> Cache<'a> { /** * Expects a slice of slices that represents lines in the file */ - pub fn put_matrix_in_cache(&self, - path: &Path, - size: u32, - file_contents: &Vec>) - -> Result { + pub fn put_matrix_in_cache( + &self, + path: &Path, + size: u32, + file_contents: &Vec>, + ) -> Result { let hash = self.get_file_hash(&path); match hash { Ok(sha1) => { - let cache_path_str = format!("{}/matrix/{}x{}/{}/{}.{}", - self.cache_dir, - size, - size, - &sha1[..10], - sha1, - CACHED_MATRIX_EXT); - let cache_dir_str = format!("{}/matrix/{}x{}/{}", self.cache_dir, size, size, &sha1[..10]); + let cache_path_str = format!( + "{}/matrix/{}x{}/{}/{}.{}", + self.cache_dir, + size, + size, + &sha1[..10], + sha1, + CACHED_MATRIX_EXT + ); + let cache_dir_str = format!( + "{}/matrix/{}x{}/{}", + self.cache_dir, + size, + size, + &sha1[..10] + ); match create_dir_all(cache_dir_str) { Ok(_) => { let cached_path = Path::new(&cache_path_str); // Save the file into the cache match File::create(&cached_path) { Ok(mut file) => { - let mut compressor = ZlibEncoder::new(Vec::new(), - Compression::default()); + let mut compressor = + ZlibEncoder::new(Vec::new(), Compression::default()); for row in file_contents { let mut row_str = - row.iter() - .fold(String::new(), - |acc, &item| acc + &format!("{},", item)); + row.iter().fold(String::new(), |acc, &item| { + acc + &format!("{},", item) + }); // remove the last comma let desire_len = row_str.len() - 1; row_str.truncate(desire_len); @@ -307,13 +321,15 @@ impl<'a> Cache<'a> { match hash { Ok(sha1) => { // Check if the file exists in the cache - let cache_path_str = format!("{}/matrix/{}x{}/{}/{}.{}", - self.cache_dir, - size, - size, - &sha1[..10], - sha1, - CACHED_MATRIX_EXT); + let cache_path_str = format!( + "{}/matrix/{}x{}/{}/{}.{}", + self.cache_dir, + size, + size, + &sha1[..10], + sha1, + CACHED_MATRIX_EXT + ); let cached_path = Path::new(&cache_path_str); // Try to open, if it does, then we can read the image in match File::open(&cached_path) { @@ -332,9 +348,7 @@ impl<'a> Cache<'a> { .trim() .split("\n") .map(|line| { - line.split(",") - .map(|f| f64::from_str(f).unwrap()) - .collect() + line.split(",").map(|f| f64::from_str(f).unwrap()).collect() }) .collect(); diff --git a/src/hash/ahash.rs b/src/hash/ahash.rs index a5a4800..c9580e0 100644 --- a/src/hash/ahash.rs +++ b/src/hash/ahash.rs @@ -9,8 +9,8 @@ use std::path::Path; use cache::Cache; -use super::{HashType, PerceptualHash, Precision, PreparedImage}; use super::prepare_image; +use super::{HashType, PerceptualHash, Precision, PreparedImage}; use self::image::{GenericImage, GenericImageView}; @@ -28,12 +28,12 @@ impl<'a> AHash<'a> { impl<'a> PerceptualHash for AHash<'a> { /** - * Calculate the ahash of the provided prepared image. - * - * # Returns - * - * A u64 representing the value of the hash - */ + * Calculate the ahash of the provided prepared image. + * + * # Returns + * + * A u64 representing the value of the hash + */ fn get_hash(&self, _: &Option) -> u64 { match self.prepared_image.image { Some(ref image) => { @@ -52,7 +52,7 @@ impl<'a> PerceptualHash for AHash<'a> { for (_, _, pixel) in image.pixels() { if pixel.0[0] as u64 >= mean { hash |= 1; - // println!("Pixel {} is >= {} therefore {:b}", pixel_sum, mean, hash); + // println!("Pixel {} is >= {} therefore {:b}", pixel_sum, mean, hash); } else { hash |= 0; // println!("Pixel {} is < {} therefore {:b}", pixel_sum, mean, hash); diff --git a/src/hash/dhash.rs b/src/hash/dhash.rs index 4e486b8..1e29520 100644 --- a/src/hash/dhash.rs +++ b/src/hash/dhash.rs @@ -8,8 +8,8 @@ use std::path::Path; use cache::Cache; -use super::{HashType, PerceptualHash, Precision, PreparedImage}; use super::prepare_image; +use super::{HashType, PerceptualHash, Precision, PreparedImage}; use self::image::{GenericImage, GenericImageView}; diff --git a/src/hash/mod.rs b/src/hash/mod.rs index 4686cb6..49691a3 100644 --- a/src/hash/mod.rs +++ b/src/hash/mod.rs @@ -6,11 +6,11 @@ extern crate dft; extern crate image; -use cache::Cache; use self::image::FilterType; +use cache::Cache; use std::f64; -use std::path::Path; use std::fmt; +use std::path::Path; mod ahash; mod dhash; @@ -59,13 +59,14 @@ pub struct PerceptualHashes<'a> { impl<'a> PerceptualHashes<'a> { pub fn similar(&self, other: &'a PerceptualHashes<'a>) -> bool { - if self.orig_path != other.orig_path && - calculate_hamming_distance(self.ahash, other.ahash) <= - HAMMING_DISTANCE_SIMILARITY_LIMIT && - calculate_hamming_distance(self.dhash, other.dhash) <= - HAMMING_DISTANCE_SIMILARITY_LIMIT && - calculate_hamming_distance(self.phash, other.phash) <= - HAMMING_DISTANCE_SIMILARITY_LIMIT { + if self.orig_path != other.orig_path + && calculate_hamming_distance(self.ahash, other.ahash) + <= HAMMING_DISTANCE_SIMILARITY_LIMIT + && calculate_hamming_distance(self.dhash, other.dhash) + <= HAMMING_DISTANCE_SIMILARITY_LIMIT + && calculate_hamming_distance(self.phash, other.phash) + <= HAMMING_DISTANCE_SIMILARITY_LIMIT + { true } else { false @@ -113,7 +114,7 @@ impl fmt::Display for HashType { match *self { HashType::AHash => write!(f, "AHash"), HashType::DHash => write!(f, "DHash"), - HashType::PHash => write!(f, "PHash") + HashType::PHash => write!(f, "PHash"), } } } @@ -140,11 +141,12 @@ pub trait PerceptualHash { * A PreparedImage struct with the required information for performing hashing * */ -pub fn prepare_image<'a>(path: &'a Path, - hash_type: &HashType, - precision: &Precision, - cache: &Option) - -> PreparedImage<'a> { +pub fn prepare_image<'a>( + path: &'a Path, + hash_type: &HashType, + precision: &Precision, + cache: &Option, +) -> PreparedImage<'a> { let image_path = path.to_str().unwrap(); let size: u32 = match *hash_type { HashType::PHash => precision.get_size() * 4, @@ -154,12 +156,10 @@ pub fn prepare_image<'a>(path: &'a Path, match *cache { Some(ref c) => { match c.get_image_from_cache(&path, size) { - Some(image) => { - PreparedImage { - orig_path: &*image_path, - image: Some(image), - } - } + Some(image) => PreparedImage { + orig_path: &*image_path, + image: Some(image), + }, None => { let processed_image = process_image(&image_path, size); // Oh, and save it in a cache @@ -205,11 +205,12 @@ fn process_image<'a>(image_path: &'a str, size: u32) -> PreparedImage<'a> { /** * Get a specific HashType hash */ -pub fn get_perceptual_hash<'a>(path: &'a Path, - precision: &Precision, - hash_type: &HashType, - cache: &Option) - -> u64 { +pub fn get_perceptual_hash<'a>( + path: &'a Path, + precision: &Precision, + hash_type: &HashType, + cache: &Option, +) -> u64 { match *hash_type { HashType::AHash => ahash::AHash::new(&path, &precision, &cache).get_hash(&cache), HashType::DHash => dhash::DHash::new(&path, &precision, &cache).get_hash(&cache), @@ -220,10 +221,11 @@ pub fn get_perceptual_hash<'a>(path: &'a Path, /** * Get all perceptual hashes for an image */ -pub fn get_perceptual_hashes<'a>(path: &'a Path, - precision: &Precision, - cache: &Option) - -> PerceptualHashes<'a> { +pub fn get_perceptual_hashes<'a>( + path: &'a Path, + precision: &Precision, + cache: &Option, +) -> PerceptualHashes<'a> { let image_path = path.to_str().unwrap(); let ahash = ahash::AHash::new(&path, &precision, &cache).get_hash(&cache); let dhash = dhash::DHash::new(&path, &precision, &cache).get_hash(&cache); diff --git a/src/hash/phash.rs b/src/hash/phash.rs index 24d338f..5bf41a6 100644 --- a/src/hash/phash.rs +++ b/src/hash/phash.rs @@ -8,11 +8,11 @@ use std::path::Path; use cache::Cache; -use super::{HashType, PerceptualHash, Precision, PreparedImage}; use super::dft; use super::dft::Transform; use super::image::Pixel; use super::prepare_image; +use super::{HashType, PerceptualHash, Precision, PreparedImage}; use self::image::{DynamicImage, GenericImage, GenericImageView}; @@ -48,14 +48,18 @@ impl<'a> PerceptualHash for PHash<'a> { // Atleast compared to opening and processing the images let data_matrix: Vec> = match *cache { Some(ref c) => { - match c.get_matrix_from_cache(&Path::new(self.prepared_image.orig_path), - width as u32) { + match c.get_matrix_from_cache( + &Path::new(self.prepared_image.orig_path), + width as u32, + ) { Some(matrix) => matrix, None => { let matrix = create_data_matrix(width, height, &image); - match c.put_matrix_in_cache(&Path::new(self.prepared_image.orig_path), - width as u32, - &matrix) { + match c.put_matrix_in_cache( + &Path::new(self.prepared_image.orig_path), + width as u32, + &matrix, + ) { Ok(_) => {} Err(e) => println!("Unable to store matrix in cache. {}", e), }; @@ -100,10 +104,7 @@ impl<'a> PerceptualHash for PHash<'a> { } } -fn create_data_matrix(width: u32, - height: u32, - image: &DynamicImage) - -> Vec> { +fn create_data_matrix(width: u32, height: u32, image: &DynamicImage) -> Vec> { let mut data_matrix: Vec> = Vec::new(); // Preparing the results for x in 0..width as usize { diff --git a/src/lib.rs b/src/lib.rs index 63a2d78..3f52cac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,8 +17,8 @@ use std::path::Path; use cache::Cache; -pub mod hash; pub mod cache; +pub mod hash; #[repr(C)] pub struct PIHash<'a> { @@ -49,40 +49,44 @@ impl<'a> PIHash<'a> { } } - pub fn get_perceptual_hash(&self, - path: &Path, - precision: &hash::Precision, - hash_type: &hash::HashType) - -> u64 { + pub fn get_perceptual_hash( + &self, + path: &Path, + precision: &hash::Precision, + hash_type: &hash::HashType, + ) -> u64 { hash::get_perceptual_hash(&path, &precision, &hash_type, &self.cache) } pub fn get_phashes(&self, path: &'a Path) -> hash::PerceptualHashes { - hash::get_perceptual_hashes(&path, - &hash::Precision::Medium, - &self.cache) + hash::get_perceptual_hashes(&path, &hash::Precision::Medium, &self.cache) } - pub fn get_ahash(&self, path: &Path) -> u64 { - hash::get_perceptual_hash(&path, - &hash::Precision::Medium, - &hash::HashType::AHash, - &self.cache) + hash::get_perceptual_hash( + &path, + &hash::Precision::Medium, + &hash::HashType::AHash, + &self.cache, + ) } pub fn get_dhash(&self, path: &Path) -> u64 { - hash::get_perceptual_hash(&path, - &hash::Precision::Medium, - &hash::HashType::DHash, - &self.cache) + hash::get_perceptual_hash( + &path, + &hash::Precision::Medium, + &hash::HashType::DHash, + &self.cache, + ) } pub fn get_phash(&self, path: &Path) -> u64 { - hash::get_perceptual_hash(&path, - &hash::Precision::Medium, - &hash::HashType::PHash, - &self.cache) + hash::get_perceptual_hash( + &path, + &hash::Precision::Medium, + &hash::HashType::PHash, + &self.cache, + ) } } @@ -125,9 +129,11 @@ pub extern "C" fn ext_get_ahash(lib: &PIHash, path_char: *const libc::c_char) -> let image_path = match path_str.to_str() { Ok(result) => result, Err(e) => { - println!("Error: {}. Unable to parse '{}'", - e, - to_hex_string(path_str.to_bytes())); + println!( + "Error: {}. Unable to parse '{}'", + e, + to_hex_string(path_str.to_bytes()) + ); panic!("Unable to parse path") } }; @@ -143,9 +149,11 @@ pub extern "C" fn ext_get_dhash(lib: &PIHash, path_char: *const libc::c_char) -> let image_path = match path_str.to_str() { Ok(result) => result, Err(e) => { - println!("Error: {}. Unable to parse '{}'", - e, - to_hex_string(path_str.to_bytes())); + println!( + "Error: {}. Unable to parse '{}'", + e, + to_hex_string(path_str.to_bytes()) + ); panic!("Unable to parse path") } }; @@ -161,9 +169,11 @@ pub extern "C" fn ext_get_phash(lib: &PIHash, path_char: *const libc::c_char) -> let image_path = match path_str.to_str() { Ok(result) => result, Err(e) => { - println!("Error: {}. Unable to parse '{}'", - e, - to_hex_string(path_str.to_bytes())); + println!( + "Error: {}. Unable to parse '{}'", + e, + to_hex_string(path_str.to_bytes()) + ); panic!("Unable to parse path") } }; @@ -186,9 +196,11 @@ pub extern "C" fn ext_get_phashes(lib: &PIHash, path_char: *const libc::c_char) let image_path = match path_str.to_str() { Ok(result) => result, Err(e) => { - println!("Error: {}. Unable to parse '{}'", - e, - to_hex_string(path_str.to_bytes())); + println!( + "Error: {}. Unable to parse '{}'", + e, + to_hex_string(path_str.to_bytes()) + ); panic!("Unable to parse path") } }; @@ -209,7 +221,6 @@ pub extern "C" fn ext_free_phashes(raw_phashes: *const libc::c_void) { } } - fn to_hex_string(bytes: &[u8]) -> String { println!("length: {}", bytes.len()); let mut strs: Vec = Vec::new(); @@ -230,9 +241,9 @@ mod tests { use cache; use hash; - use super::PIHash; #[cfg(feature = "bench")] use super::test::Bencher; + use super::PIHash; #[test] fn test_can_get_test_images() { @@ -263,21 +274,25 @@ mod tests { * Updated test function. Assumes 3 images to a set and no hamming distances. * We don't need to confirm that the hamming distance calculation works in these tests. */ - fn test_imageset_hash(hash_type: hash::HashType, - hash_precision: hash::Precision, - max_hamming_distance: u64, - image_paths: [&Path; 3], - image_hashes: [u64; 3], - lib: &PIHash) { + fn test_imageset_hash( + hash_type: hash::HashType, + hash_precision: hash::Precision, + max_hamming_distance: u64, + image_paths: [&Path; 3], + image_hashes: [u64; 3], + lib: &PIHash, + ) { let mut hashes: [u64; 3] = [0; 3]; for index in 0..image_paths.len() { let image_path = image_paths[index]; let calculated_hash = lib.get_perceptual_hash(&image_path, &hash_precision, &hash_type); - println!("[{}] Image hashes for [{}] expected: [{}] actual: [{}]", - hash_type, - image_path.to_str().unwrap(), - image_hashes[index], - calculated_hash); + println!( + "[{}] Image hashes for [{}] expected: [{}] actual: [{}]", + hash_type, + image_path.to_str().unwrap(), + image_hashes[index], + calculated_hash + ); assert_eq!(calculated_hash, image_hashes[index]); hashes[index] = calculated_hash; } @@ -308,65 +323,74 @@ mod tests { let sample_01_images: [&Path; 3] = [ &Path::new("./test_images/sample_01_large.jpg"), &Path::new("./test_images/sample_01_medium.jpg"), - &Path::new("./test_images/sample_01_small.jpg")]; - let sample_01_hashes: [u64; 3] = [ - 857051991849750, - 857051991849750, - 857051991849750]; - test_imageset_hash(hash::HashType::AHash, - hash::Precision::Medium, - 1u64, - sample_01_images, - sample_01_hashes, - &lib); + &Path::new("./test_images/sample_01_small.jpg"), + ]; + let sample_01_hashes: [u64; 3] = [857051991849750, 857051991849750, 857051991849750]; + test_imageset_hash( + hash::HashType::AHash, + hash::Precision::Medium, + 1u64, + sample_01_images, + sample_01_hashes, + &lib, + ); // Sample_02 tests let sample_02_images: [&Path; 3] = [ &Path::new("./test_images/sample_02_large.jpg"), &Path::new("./test_images/sample_02_medium.jpg"), - &Path::new("./test_images/sample_02_small.jpg")]; + &Path::new("./test_images/sample_02_small.jpg"), + ]; let sample_02_hashes: [u64; 3] = [ 18446744073441116160, 18446744073441116160, - 18446744073441116160]; - test_imageset_hash(hash::HashType::AHash, - hash::Precision::Medium, - 3u64, - sample_02_images, - sample_02_hashes, - &lib); + 18446744073441116160, + ]; + test_imageset_hash( + hash::HashType::AHash, + hash::Precision::Medium, + 3u64, + sample_02_images, + sample_02_hashes, + &lib, + ); // Sample_03 tests let sample_03_images: [&Path; 3] = [ &Path::new("./test_images/sample_03_large.jpg"), &Path::new("./test_images/sample_03_medium.jpg"), - &Path::new("./test_images/sample_03_small.jpg")]; - let sample_03_hashes: [u64; 3] = [ - 135670932300497406, - 135670932300497406, - 135670932300497406]; - test_imageset_hash(hash::HashType::AHash, - hash::Precision::Medium, - 1u64, - sample_03_images, - sample_03_hashes, - &lib); + &Path::new("./test_images/sample_03_small.jpg"), + ]; + let sample_03_hashes: [u64; 3] = + [135670932300497406, 135670932300497406, 135670932300497406]; + test_imageset_hash( + hash::HashType::AHash, + hash::Precision::Medium, + 1u64, + sample_03_images, + sample_03_hashes, + &lib, + ); // Sample_04 tests let sample_04_images: [&Path; 3] = [ &Path::new("./test_images/sample_04_large.jpg"), &Path::new("./test_images/sample_04_medium.jpg"), - &Path::new("./test_images/sample_04_small.jpg")]; + &Path::new("./test_images/sample_04_small.jpg"), + ]; let sample_04_hashes: [u64; 3] = [ 18446460933225054208, 18446460933225054208, - 18446460933225054208]; - test_imageset_hash(hash::HashType::AHash, - hash::Precision::Medium, - 0u64, - sample_04_images, - sample_04_hashes, - &lib); + 18446460933225054208, + ]; + test_imageset_hash( + hash::HashType::AHash, + hash::Precision::Medium, + 0u64, + sample_04_images, + sample_04_hashes, + &lib, + ); // Clean_Cache // super::teardown(); @@ -381,65 +405,78 @@ mod tests { let sample_01_images: [&Path; 3] = [ &Path::new("./test_images/sample_01_large.jpg"), &Path::new("./test_images/sample_01_medium.jpg"), - &Path::new("./test_images/sample_01_small.jpg")]; + &Path::new("./test_images/sample_01_small.jpg"), + ]; let sample_01_hashes: [u64; 3] = [ 3404580580803739582, 3404580580803739582, - 3404580580803739582]; - test_imageset_hash(hash::HashType::DHash, - hash::Precision::Medium, - 0u64, - sample_01_images, - sample_01_hashes, - &lib); + 3404580580803739582, + ]; + test_imageset_hash( + hash::HashType::DHash, + hash::Precision::Medium, + 0u64, + sample_01_images, + sample_01_hashes, + &lib, + ); // Sample_02 tests let sample_02_images: [&Path; 3] = [ &Path::new("./test_images/sample_02_large.jpg"), &Path::new("./test_images/sample_02_medium.jpg"), - &Path::new("./test_images/sample_02_small.jpg")]; + &Path::new("./test_images/sample_02_small.jpg"), + ]; let sample_02_hashes: [u64; 3] = [ 14726771606135242753, 14726771606135242753, - 14726771606135242753]; - test_imageset_hash(hash::HashType::DHash, - hash::Precision::Medium, - 0u64, - sample_02_images, - sample_02_hashes, - &lib); + 14726771606135242753, + ]; + test_imageset_hash( + hash::HashType::DHash, + hash::Precision::Medium, + 0u64, + sample_02_images, + sample_02_hashes, + &lib, + ); // Sample_03 tests let sample_03_images: [&Path; 3] = [ &Path::new("./test_images/sample_03_large.jpg"), &Path::new("./test_images/sample_03_medium.jpg"), - &Path::new("./test_images/sample_03_small.jpg")]; - let sample_03_hashes: [u64; 3] = [ - 144115181601817086, - 144115181601817086, - 144115181601817086]; - test_imageset_hash(hash::HashType::DHash, - hash::Precision::Medium, - 0u64, - sample_03_images, - sample_03_hashes, - &lib); + &Path::new("./test_images/sample_03_small.jpg"), + ]; + let sample_03_hashes: [u64; 3] = + [144115181601817086, 144115181601817086, 144115181601817086]; + test_imageset_hash( + hash::HashType::DHash, + hash::Precision::Medium, + 0u64, + sample_03_images, + sample_03_hashes, + &lib, + ); // Sample_04 tests let sample_04_images: [&Path; 3] = [ &Path::new("./test_images/sample_04_large.jpg"), &Path::new("./test_images/sample_04_medium.jpg"), - &Path::new("./test_images/sample_04_small.jpg")]; + &Path::new("./test_images/sample_04_small.jpg"), + ]; let sample_04_hashes: [u64; 3] = [ 18374262188442386433, 18374262188442386433, - 18374262188442386433]; - test_imageset_hash(hash::HashType::DHash, - hash::Precision::Medium, - 1u64, - sample_04_images, - sample_04_hashes, - &lib); + 18374262188442386433, + ]; + test_imageset_hash( + hash::HashType::DHash, + hash::Precision::Medium, + 1u64, + sample_04_images, + sample_04_hashes, + &lib, + ); // Clean_Cache // super::teardown(); @@ -454,65 +491,77 @@ mod tests { let sample_01_images: [&Path; 3] = [ &Path::new("./test_images/sample_01_large.jpg"), &Path::new("./test_images/sample_01_medium.jpg"), - &Path::new("./test_images/sample_01_small.jpg")]; - let sample_01_hashes: [u64; 3] = [ - 72357778504597504, - 72357778504597504, - 72357778504597504]; - test_imageset_hash(hash::HashType::PHash, - hash::Precision::Medium, - 1u64, - sample_01_images, - sample_01_hashes, - &lib); + &Path::new("./test_images/sample_01_small.jpg"), + ]; + let sample_01_hashes: [u64; 3] = [72357778504597504, 72357778504597504, 72357778504597504]; + test_imageset_hash( + hash::HashType::PHash, + hash::Precision::Medium, + 1u64, + sample_01_images, + sample_01_hashes, + &lib, + ); // Sample_02 tests let sample_02_images: [&Path; 3] = [ &Path::new("./test_images/sample_02_large.jpg"), &Path::new("./test_images/sample_02_medium.jpg"), - &Path::new("./test_images/sample_02_small.jpg")]; + &Path::new("./test_images/sample_02_small.jpg"), + ]; let sample_02_hashes: [u64; 3] = [ 5332332327550844928, 5332332327550844928, - 5332332327550844928]; - test_imageset_hash(hash::HashType::PHash, - hash::Precision::Medium, - 1u64, - sample_02_images, - sample_02_hashes, - &lib); + 5332332327550844928, + ]; + test_imageset_hash( + hash::HashType::PHash, + hash::Precision::Medium, + 1u64, + sample_02_images, + sample_02_hashes, + &lib, + ); // Sample_03 tests let sample_03_images: [&Path; 3] = [ &Path::new("./test_images/sample_03_large.jpg"), &Path::new("./test_images/sample_03_medium.jpg"), - &Path::new("./test_images/sample_03_small.jpg")]; + &Path::new("./test_images/sample_03_small.jpg"), + ]; let sample_03_hashes: [u64; 3] = [ 6917529027641081856, 6917529027641081856, - 6917529027641081856]; - test_imageset_hash(hash::HashType::PHash, - hash::Precision::Medium, - 0u64, - sample_03_images, - sample_03_hashes, - &lib); + 6917529027641081856, + ]; + test_imageset_hash( + hash::HashType::PHash, + hash::Precision::Medium, + 0u64, + sample_03_images, + sample_03_hashes, + &lib, + ); // Sample_04 tests let sample_04_images: [&Path; 3] = [ &Path::new("./test_images/sample_04_large.jpg"), &Path::new("./test_images/sample_04_medium.jpg"), - &Path::new("./test_images/sample_04_small.jpg")]; + &Path::new("./test_images/sample_04_small.jpg"), + ]; let sample_04_hashes: [u64; 3] = [ 10997931646002397184, 10997931646002397184, - 10997931646002397184]; - test_imageset_hash(hash::HashType::PHash, - hash::Precision::Medium, - 3u64, - sample_04_images, - sample_04_hashes, - &lib); + 10997931646002397184, + ]; + test_imageset_hash( + hash::HashType::PHash, + hash::Precision::Medium, + 3u64, + sample_04_images, + sample_04_hashes, + &lib, + ); // Clean_Cache // super::teardown(); @@ -526,15 +575,19 @@ mod tests { // Setup the caches to make sure we're good to properly bench // All phashes so that the matricies are pulled from cache as well - lib.get_perceptual_hash(&Path::new("./test_images/sample_01_large.jpg"), - &hash::Precision::Medium, - &hash::HashType::PHash); + lib.get_perceptual_hash( + &Path::new("./test_images/sample_01_large.jpg"), + &hash::Precision::Medium, + &hash::HashType::PHash, + ); bench.iter(|| { // Sample_01 Bench - lib.get_perceptual_hash(&Path::new("./test_images/sample_01_large.jpg"), - &hash::Precision::Medium, - &hash::HashType::PHash); + lib.get_perceptual_hash( + &Path::new("./test_images/sample_01_large.jpg"), + &hash::Precision::Medium, + &hash::HashType::PHash, + ); }) } @@ -546,9 +599,11 @@ mod tests { bench.iter(|| { // Sample_01 Bench - lib.get_perceptual_hash(&Path::new("./test_images/sample_01_large.jpg"), - &hash::Precision::Medium, - &hash::HashType::PHash); + lib.get_perceptual_hash( + &Path::new("./test_images/sample_01_large.jpg"), + &hash::Precision::Medium, + &hash::HashType::PHash, + ); }) } } diff --git a/src/main.rs b/src/main.rs index e65e131..36bc334 100644 --- a/src/main.rs +++ b/src/main.rs @@ -65,10 +65,11 @@ fn main() { let mut comparison_hashes: Vec = Vec::new(); for index in 0..args.arg_comparison.len() { - comparison_hashes - .push(get_requested_perceptual_hashes(&lib, - &Path::new(&args.arg_comparison[index]), - &args)); + comparison_hashes.push(get_requested_perceptual_hashes( + &lib, + &Path::new(&args.arg_comparison[index]), + &args, + )); } let mut similar_images: Vec<&str> = Vec::new(); @@ -94,23 +95,22 @@ ahash: {} dhash: {} phash: {} "#, - hashes.orig_path, - hashes.ahash, - hashes.dhash, - hashes.phash); + hashes.orig_path, hashes.ahash, hashes.dhash, hashes.phash + ); println!("{}", hash_result); } } fn flags_get_all_perceptual_hashes(args: &Args) -> bool { - (args.flag_ahash && args.flag_dhash && args.flag_phash) || - (!args.flag_ahash && !args.flag_dhash && !args.flag_phash) + (args.flag_ahash && args.flag_dhash && args.flag_phash) + || (!args.flag_ahash && !args.flag_dhash && !args.flag_phash) } -fn get_requested_perceptual_hashes<'a>(lib: &pihash::PIHash, - image_path: &'a Path, - args: &Args) - -> pihash::hash::PerceptualHashes<'a> { +fn get_requested_perceptual_hashes<'a>( + lib: &pihash::PIHash, + image_path: &'a Path, + args: &Args, +) -> pihash::hash::PerceptualHashes<'a> { let ahash = if args.flag_ahash || flags_get_all_perceptual_hashes(&args) { lib.get_ahash(&image_path) } else {