Browse Source

Ran rustfmt

develop
Drew Short 9 years ago
parent
commit
dc8453dc67
  1. 99
      src/cache.rs
  2. 6
      src/hash/ahash.rs
  3. 6
      src/hash/dhash.rs
  4. 17
      src/hash/mod.rs
  5. 19
      src/hash/phash.rs
  6. 621
      src/lib.rs
  7. 11
      src/main.rs

99
src/cache.rs

@ -34,7 +34,9 @@ struct CacheMetadata {
} }
impl Default for CacheMetadata { impl Default for CacheMetadata {
fn default() -> CacheMetadata { CacheMetadata { cache_version: CACHE_VERSION } }
fn default() -> CacheMetadata {
CacheMetadata { cache_version: CACHE_VERSION }
}
} }
impl PartialEq<CacheMetadata> for CacheMetadata { impl PartialEq<CacheMetadata> for CacheMetadata {
@ -56,7 +58,12 @@ pub struct Cache<'a> {
} }
impl<'a> Default for Cache<'a> { impl<'a> Default for Cache<'a> {
fn default() -> Cache<'a> { Cache {cache_dir: CACHE_DIR, use_cache: true } }
fn default() -> Cache<'a> {
Cache {
cache_dir: CACHE_DIR,
use_cache: true,
}
}
} }
impl<'a> Cache<'a> { impl<'a> Cache<'a> {
@ -75,40 +82,42 @@ impl<'a> Cache<'a> {
let mut loaded_metadata_string = String::new(); let mut loaded_metadata_string = String::new();
match file.read_to_string(&mut loaded_metadata_string) { match file.read_to_string(&mut loaded_metadata_string) {
Ok(_) => { Ok(_) => {
let loaded_metadata: CacheMetadata = match json::decode(&loaded_metadata_string) {
Ok(data) => data,
Err(_) => CacheMetadata { cache_version: 0 },
};
let loaded_metadata: CacheMetadata =
match json::decode(&loaded_metadata_string) {
Ok(data) => data,
Err(_) => CacheMetadata { cache_version: 0 },
};
// If they match, continue // If they match, continue
if current_metadata != loaded_metadata { if current_metadata != loaded_metadata {
// If they don't wipe the cache to start new // If they don't wipe the cache to start new
match remove_dir_all(self.cache_dir) { match remove_dir_all(self.cache_dir) {
Ok(_) => {
Ok(_) => {
match create_dir_all(self.cache_dir) { match create_dir_all(self.cache_dir) {
Ok(_) => (), Ok(_) => (),
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
},
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
}; };
}; };
},
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
}; };
},
// Metadata file doesn't exist, do nothing assume all is well, create new metadata file
Err(_) => {},
}
// Metadata file doesn't exist, do nothing assume all is well,
// create new metadata file
Err(_) => {}
}; };
let encoded_cache_metadata = json::encode(&current_metadata).unwrap(); let encoded_cache_metadata = json::encode(&current_metadata).unwrap();
match File::create(&metadata_path) { match File::create(&metadata_path) {
Ok(mut file) => { Ok(mut file) => {
let _ = file.write(&encoded_cache_metadata.as_bytes()); let _ = file.write(&encoded_cache_metadata.as_bytes());
Ok(()) Ok(())
},
Err(e) => Err(e)
}
Err(e) => Err(e),
} }
},
}
Err(e) => Err(e), Err(e) => Err(e),
} }
} }
@ -136,11 +145,11 @@ impl<'a> Cache<'a> {
/** /**
* Put an image buffer in the cache * Put an image buffer in the cache
*/ */
pub fn put_image_in_cache(&self,
path: &Path,
size: u32,
image: &ImageBuffer<image::Luma<u8>, Vec<u8>>)
-> Result<bool, Error> {
pub fn put_image_in_cache(&self,
path: &Path,
size: u32,
image: &ImageBuffer<image::Luma<u8>, Vec<u8>>)
-> Result<bool, Error> {
let hash = self.get_file_hash(&path); let hash = self.get_file_hash(&path);
match hash { match hash {
Ok(sha1) => { Ok(sha1) => {
@ -162,7 +171,7 @@ impl<'a> Cache<'a> {
return Err(e); return Err(e);
} }
} }
},
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -209,21 +218,28 @@ impl<'a> Cache<'a> {
None None
} }
} }
} else { None }
} else {
None
}
} }
/** /**
* Expects a slice of slices that represents lines in the file * Expects a slice of slices that represents lines in the file
*/ */
pub fn put_matrix_in_cache(&self, pub fn put_matrix_in_cache(&self,
path: &Path,
size: u32,
file_contents: &Vec<Vec<f64>>)
-> Result<bool, Error> {
path: &Path,
size: u32,
file_contents: &Vec<Vec<f64>>)
-> Result<bool, Error> {
let hash = self.get_file_hash(&path); let hash = self.get_file_hash(&path);
match hash { match hash {
Ok(sha1) => { Ok(sha1) => {
let cache_path_str = format!("{}/matrix/{}x{}/{}.{}", self.cache_dir, size, size, sha1, CACHED_MATRIX_EXT);
let cache_path_str = format!("{}/matrix/{}x{}/{}.{}",
self.cache_dir,
size,
size,
sha1,
CACHED_MATRIX_EXT);
let cache_dir_str = format!("{}/matrix/{}x{}", self.cache_dir, size, size); let cache_dir_str = format!("{}/matrix/{}x{}", self.cache_dir, size, size);
match create_dir_all(cache_dir_str) { match create_dir_all(cache_dir_str) {
Ok(_) => { Ok(_) => {
@ -231,10 +247,14 @@ impl<'a> Cache<'a> {
// Save the file into the cache // Save the file into the cache
match File::create(&cached_path) { match File::create(&cached_path) {
Ok(mut file) => { 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 { for row in file_contents {
let mut row_str = row.iter().fold(String::new(), let mut row_str = row.iter().fold(String::new(),
|acc, &item| acc + &format!("{},", item));
|acc, &item| {
acc +
&format!("{},", item)
});
// remove the last comma // remove the last comma
let desire_len = row_str.len() - 1; let desire_len = row_str.len() - 1;
row_str.truncate(desire_len); row_str.truncate(desire_len);
@ -255,7 +275,7 @@ impl<'a> Cache<'a> {
return Err(e); return Err(e);
} }
} }
},
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -270,16 +290,18 @@ impl<'a> Cache<'a> {
/** /**
* Get a matrix out of the cache * Get a matrix out of the cache
*/ */
pub fn get_matrix_from_cache(&self,
path: &Path,
size: u32)
-> Option<Vec<Vec<f64>>> {
pub fn get_matrix_from_cache(&self, path: &Path, size: u32) -> Option<Vec<Vec<f64>>> {
if self.use_cache { if self.use_cache {
let hash = self.get_file_hash(&path); let hash = self.get_file_hash(&path);
match hash { match hash {
Ok(sha1) => { Ok(sha1) => {
// Check if the file exists in the cache // Check if the file exists in the cache
let cache_path_str = format!("{}/matrix/{}x{}/{}.{}", CACHE_DIR, size, size, sha1, CACHED_MATRIX_EXT);
let cache_path_str = format!("{}/matrix/{}x{}/{}.{}",
CACHE_DIR,
size,
size,
sha1,
CACHED_MATRIX_EXT);
let cached_path = Path::new(&cache_path_str); let cached_path = Path::new(&cache_path_str);
// Try to open, if it does, then we can read the image in // Try to open, if it does, then we can read the image in
match File::open(&cached_path) { match File::open(&cached_path) {
@ -299,7 +321,8 @@ impl<'a> Cache<'a> {
.map(|line| { .map(|line| {
line.split(",") line.split(",")
.map(|f| { .map(|f| {
f64::from_str(f).unwrap()
f64::from_str(f)
.unwrap()
}) })
.collect() .collect()
}) })
@ -317,7 +340,9 @@ impl<'a> Cache<'a> {
None None
} }
} }
} else { None }
} else {
None
}
} }
} }

6
src/hash/ahash.rs

@ -15,7 +15,9 @@ pub struct AHash<'a> {
impl<'a> AHash<'a> { impl<'a> AHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
AHash { prepared_image: Box::new(prepare_image(&path, &HashType::AHash, &precision, &cache)) }
AHash {
prepared_image: Box::new(prepare_image(&path, &HashType::AHash, &precision, &cache)),
}
} }
} }
@ -58,4 +60,4 @@ impl<'a> PerceptualHash for AHash<'a> {
hash hash
} }
}
}

6
src/hash/dhash.rs

@ -15,7 +15,9 @@ pub struct DHash<'a> {
impl<'a> DHash<'a> { impl<'a> DHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
DHash { prepared_image: Box::new(prepare_image(&path, &HashType::DHash, &precision, &cache)) }
DHash {
prepared_image: Box::new(prepare_image(&path, &HashType::DHash, &precision, &cache)),
}
} }
} }
@ -59,4 +61,4 @@ impl<'a> PerceptualHash for DHash<'a> {
hash hash
} }
}
}

17
src/hash/mod.rs

@ -128,7 +128,7 @@ pub fn prepare_image<'a>(path: &'a Path,
PreparedImage { PreparedImage {
orig_path: &*image_path, orig_path: &*image_path,
image: image, image: image,
cache: &cache
cache: &cache,
} }
} }
None => { None => {
@ -152,18 +152,25 @@ pub fn prepare_image<'a>(path: &'a Path,
/** /**
* Get a specific HashType hash * Get a specific HashType hash
*/ */
pub fn get_perceptual_hash<'a>(path: &'a Path, precision: &Precision, hash_type: &HashType, cache: &Cache) -> u64 {
pub fn get_perceptual_hash<'a>(path: &'a Path,
precision: &Precision,
hash_type: &HashType,
cache: &Cache)
-> u64 {
match *hash_type { match *hash_type {
HashType::AHash => ahash::AHash::new(&path, &precision, &cache).get_hash(), HashType::AHash => ahash::AHash::new(&path, &precision, &cache).get_hash(),
HashType::DHash => dhash::DHash::new(&path, &precision, &cache).get_hash(), HashType::DHash => dhash::DHash::new(&path, &precision, &cache).get_hash(),
HashType::PHash => phash::PHash::new(&path, &precision, &cache).get_hash()
HashType::PHash => phash::PHash::new(&path, &precision, &cache).get_hash(),
} }
} }
/** /**
* Get all perceptual hashes for an image * Get all perceptual hashes for an image
*/ */
pub fn get_perceptual_hashes<'a>(path: &'a Path, precision: &Precision, cache: &Cache) -> PerceptualHashes<'a> {
pub fn get_perceptual_hashes<'a>(path: &'a Path,
precision: &Precision,
cache: &Cache)
-> PerceptualHashes<'a> {
let image_path = path.to_str().unwrap(); let image_path = path.to_str().unwrap();
let ahash = ahash::AHash::new(&path, &precision, &cache).get_hash(); let ahash = ahash::AHash::new(&path, &precision, &cache).get_hash();
let dhash = dhash::DHash::new(&path, &precision, &cache).get_hash(); let dhash = dhash::DHash::new(&path, &precision, &cache).get_hash();
@ -194,4 +201,4 @@ pub fn calculate_hamming_distance(hash1: u64, hash2: u64) -> u64 {
} }
} }
hamming hamming
}
}

19
src/hash/phash.rs

@ -17,7 +17,9 @@ pub struct PHash<'a> {
impl<'a> PHash<'a> { impl<'a> PHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
PHash { prepared_image: Box::new(prepare_image(&path, &HashType::PHash, &precision, &cache)) }
PHash {
prepared_image: Box::new(prepare_image(&path, &HashType::PHash, &precision, &cache)),
}
} }
} }
@ -39,8 +41,9 @@ impl<'a> PerceptualHash for PHash<'a> {
// Pretty fast already, so caching doesn't make a huge difference // Pretty fast already, so caching doesn't make a huge difference
// Atleast compared to opening and processing the images // Atleast compared to opening and processing the images
let mut data_matrix: Vec<Vec<f64>> = Vec::new(); let mut data_matrix: Vec<Vec<f64>> = Vec::new();
match self.prepared_image.cache.get_matrix_from_cache(&Path::new(self.prepared_image.orig_path),
width as u32) {
match self.prepared_image
.cache
.get_matrix_from_cache(&Path::new(self.prepared_image.orig_path), width as u32) {
Some(matrix) => data_matrix = matrix, Some(matrix) => data_matrix = matrix,
None => { None => {
// Preparing the results // Preparing the results
@ -60,9 +63,11 @@ impl<'a> PerceptualHash for PHash<'a> {
// Perform the 2D DFT operation on our matrix // Perform the 2D DFT operation on our matrix
calculate_2d_dft(&mut data_matrix); calculate_2d_dft(&mut data_matrix);
// Store this DFT in the cache // Store this DFT in the cache
match self.prepared_image.cache.put_matrix_in_cache(&Path::new(self.prepared_image.orig_path),
width as u32,
&data_matrix) {
match self.prepared_image
.cache
.put_matrix_in_cache(&Path::new(self.prepared_image.orig_path),
width as u32,
&data_matrix) {
Ok(_) => {} Ok(_) => {}
Err(e) => println!("Unable to store matrix in cache. {}", e), Err(e) => println!("Unable to store matrix in cache. {}", e),
}; };
@ -216,4 +221,4 @@ fn test_2d_dft() {
assert!(test_matrix[3][1] == 2_f64); assert!(test_matrix[3][1] == 2_f64);
assert!(test_matrix[3][2] == -2_f64); assert!(test_matrix[3][2] == -2_f64);
assert!(test_matrix[3][3] == 0_f64); assert!(test_matrix[3][3] == 0_f64);
}
}

621
src/lib.rs

@ -13,304 +13,351 @@ use std::path::Path;
use std::ffi::CStr; use std::ffi::CStr;
use cache::Cache; use cache::Cache;
static LIB_CACHE: Cache<'static> = Cache { cache_dir: cache::CACHE_DIR, use_cache: true };
static LIB_CACHE: Cache<'static> = Cache {
cache_dir: cache::CACHE_DIR,
use_cache: true,
};
/** /**
* Prepare the library for work. * Prepare the library for work.
* *
* Not performing this step may cause parts to fail. * Not performing this step may cause parts to fail.
*/ */
#[no_mangle]
pub extern "C" fn init() {
match LIB_CACHE.init() {
Ok(_) => {}
Err(e) => println!("Error: {}", e),
}
}
#[no_mangle]
pub extern "C" fn init() {
match LIB_CACHE.init() {
Ok(_) => {}
Err(e) => println!("Error: {}", e),
}
}
/** /**
* Teardown for the library * Teardown for the library
*/ */
#[no_mangle]
pub extern "C" fn teardown() {
match LIB_CACHE.clean() {
Ok(_) => {}
Err(e) => println!("Error: {}", e),
}
}
pub fn get_phashes(path: &Path) -> hash::PerceptualHashes {
hash::get_perceptual_hashes(path, &hash::Precision::Medium, &LIB_CACHE)
}
pub fn get_ahash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path, &hash::Precision::Medium, &hash::HashType::AHash, &LIB_CACHE)
}
pub fn get_dhash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path, &hash::Precision::Medium, &hash::HashType::DHash, &LIB_CACHE)
}
pub fn get_phash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path, &hash::Precision::Medium, &hash::HashType::DHash, &LIB_CACHE)
}
pub fn get_hamming_distance(hash1: u64, hash2: u64) -> u64 {
hash::calculate_hamming_distance(hash1, hash2)
}
// External proxies for the get_*hash methods
#[no_mangle]
pub extern "C" fn ext_get_ahash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_ahash(&path)
}
}
#[no_mangle]
pub extern "C" fn ext_get_dhash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_dhash(&path)
}
}
#[no_mangle]
pub extern "C" fn ext_get_phash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_phash(&path)
}
}
fn to_hex_string(bytes: &[u8]) -> String {
println!("length: {}", bytes.len());
let mut strs: Vec<String> = Vec::new();
for byte in bytes {
// println!("{:02x}", byte);
strs.push(format!("{:02x}", byte));
}
strs.join("\\x")
}
// Module for the tests
//
#[no_mangle]
pub extern "C" fn teardown() {
match LIB_CACHE.clean() {
Ok(_) => {}
Err(e) => println!("Error: {}", e),
}
}
pub fn get_phashes(path: &Path) -> hash::PerceptualHashes {
hash::get_perceptual_hashes(path, &hash::Precision::Medium, &LIB_CACHE)
}
pub fn get_ahash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path,
&hash::Precision::Medium,
&hash::HashType::AHash,
&LIB_CACHE)
}
pub fn get_dhash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path,
&hash::Precision::Medium,
&hash::HashType::DHash,
&LIB_CACHE)
}
pub fn get_phash(path: &Path) -> u64 {
hash::get_perceptual_hash(&path,
&hash::Precision::Medium,
&hash::HashType::DHash,
&LIB_CACHE)
}
pub fn get_hamming_distance(hash1: u64, hash2: u64) -> u64 {
hash::calculate_hamming_distance(hash1, hash2)
}
// External proxies for the get_*hash methods
#[no_mangle]
pub extern "C" fn ext_get_ahash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_ahash(&path)
}
}
#[no_mangle]
pub extern "C" fn ext_get_dhash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_dhash(&path)
}
}
#[no_mangle]
pub extern "C" fn ext_get_phash(path_char: *const libc::c_char) -> libc::uint64_t {
unsafe {
let path_str = CStr::from_ptr(path_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()));
panic!("Unable to parse path")
}
};
let path = Path::new(&image_path);
get_phash(&path)
}
}
fn to_hex_string(bytes: &[u8]) -> String {
println!("length: {}", bytes.len());
let mut strs: Vec<String> = Vec::new();
for byte in bytes {
// println!("{:02x}", byte);
strs.push(format!("{:02x}", byte));
}
strs.join("\\x")
}
// Module for the tests
//
#[cfg(test)] #[cfg(test)]
mod tests {
use std::fs;
use std::path::Path;
use hash;
#[test]
fn test_can_get_test_images() {
let paths = fs::read_dir(&Path::new("./test_images")).unwrap();
let mut num_paths = 0;
for path in paths {
let orig_path = path.unwrap().path();
let ext = Path::new(&orig_path).extension();
match ext {
Some(_) => {
if ext.unwrap() == "jpg" {
num_paths += 1;
println!("Is a image {}: {:?}", num_paths, orig_path) ;
}
}
_ => {
println!("Not an image: {:?}", orig_path) ;
continue;
}
}
// println!("Name: {}", path.unwrap().path().display())
}
// Currently 12 images in the test imaages directory
assert!(num_paths == 12);
}
/**
mod tests {
use std::fs;
use std::path::Path;
use hash;
#[test]
fn test_can_get_test_images() {
let paths = fs::read_dir(&Path::new("./test_images")).unwrap();
let mut num_paths = 0;
for path in paths {
let orig_path = path.unwrap().path();
let ext = Path::new(&orig_path).extension();
match ext {
Some(_) => {
if ext.unwrap() == "jpg" {
num_paths += 1;
println!("Is a image {}: {:?}", num_paths, orig_path) ;
}
}
_ => {
println!("Not an image: {:?}", orig_path) ;
continue;
}
}
// println!("Name: {}", path.unwrap().path().display())
}
// Currently 12 images in the test imaages directory
assert!(num_paths == 12);
}
/**
* Updated test function. Assumes 3 images to a set and no hamming distances. * 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. * 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,
image_paths: [&Path; 3],
image_hashes: [u64; 3]) {
for index in 0..image_paths.len() {
let image_path = image_paths[index];
let calculated_hash = hash::get_perceptual_hash(&image_path, &hash_precision, &hash_type, &super::LIB_CACHE);
println!("Image hashes for '{}': expected: {} actual: {}",
image_path.to_str().unwrap(),
image_hashes[index],
calculated_hash);
assert!(calculated_hash == image_hashes[index]);
}
}
#[test]
fn test_confirm_ahash_results() {
// Prep_Cache
super::init();
// Sample_01 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, sample_01_images, sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [18446744073441116160,
18446744073441116160,
18446744073441116160];
test_imageset_hash(hash::HashType::AHash, hash::Precision::Medium, sample_02_images, sample_02_hashes);
// 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, sample_03_images, sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [18446460933225054208,
18446460933090836480,
18446460933090836480];
test_imageset_hash(hash::HashType::AHash, hash::Precision::Medium, sample_04_images, sample_04_hashes);
// Clean_Cache
// super::teardown();
}
#[test]
fn test_confirm_dhash_results() {
// Prep_Cache
super::init();
// Sample_01 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] = [7937395827556495926,
7937395827556495926,
7939647627370181174];
test_imageset_hash(hash::HashType::DHash, hash::Precision::Medium, sample_01_images, sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [11009829669713008949,
11009829670249879861,
11009829669713008949];
test_imageset_hash(hash::HashType::DHash, hash::Precision::Medium, sample_02_images, sample_02_hashes);
// 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] = [225528496439353286,
225528496439353286,
226654396346195908];
test_imageset_hash(hash::HashType::DHash, hash::Precision::Medium, sample_03_images, sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [14620651386429567209,
14620651386429567209,
14620651386429567209];
test_imageset_hash(hash::HashType::DHash, hash::Precision::Medium, sample_04_images, sample_04_hashes);
// Clean_Cache
// super::teardown();
}
#[test]
fn test_confirm_phash_results() {
// Prep_Cache
super::init();
// Sample_01 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, sample_01_images, sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [5332332327550844928,
5332332327550844928,
5332332327550844928];
test_imageset_hash(hash::HashType::PHash, hash::Precision::Medium, sample_02_images, sample_02_hashes);
// 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] = [6917529027641081856,
6917529027641081856,
6917529027641081856];
test_imageset_hash(hash::HashType::PHash, hash::Precision::Medium, sample_03_images, sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [10997931646002397184,
10997931646002397184,
11142046834078253056];
test_imageset_hash(hash::HashType::PHash, hash::Precision::Medium, sample_04_images, sample_04_hashes);
// Clean_Cache
// super::teardown();
}
}
fn test_imageset_hash(hash_type: hash::HashType,
hash_precision: hash::Precision,
image_paths: [&Path; 3],
image_hashes: [u64; 3]) {
for index in 0..image_paths.len() {
let image_path = image_paths[index];
let calculated_hash = hash::get_perceptual_hash(&image_path,
&hash_precision,
&hash_type,
&super::LIB_CACHE);
println!("Image hashes for '{}': expected: {} actual: {}",
image_path.to_str().unwrap(),
image_hashes[index],
calculated_hash);
assert!(calculated_hash == image_hashes[index]);
}
}
#[test]
fn test_confirm_ahash_results() {
// Prep_Cache
super::init();
// Sample_01 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,
sample_01_images,
sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [18446744073441116160,
18446744073441116160,
18446744073441116160];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
sample_02_images,
sample_02_hashes);
// 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,
sample_03_images,
sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [18446460933225054208,
18446460933090836480,
18446460933090836480];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
sample_04_images,
sample_04_hashes);
// Clean_Cache
// super::teardown();
}
#[test]
fn test_confirm_dhash_results() {
// Prep_Cache
super::init();
// Sample_01 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] = [7937395827556495926,
7937395827556495926,
7939647627370181174];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
sample_01_images,
sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [11009829669713008949,
11009829670249879861,
11009829669713008949];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
sample_02_images,
sample_02_hashes);
// 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] = [225528496439353286,
225528496439353286,
226654396346195908];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
sample_03_images,
sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [14620651386429567209,
14620651386429567209,
14620651386429567209];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
sample_04_images,
sample_04_hashes);
// Clean_Cache
// super::teardown();
}
#[test]
fn test_confirm_phash_results() {
// Prep_Cache
super::init();
// Sample_01 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,
sample_01_images,
sample_01_hashes);
// 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")];
let sample_02_hashes: [u64; 3] = [5332332327550844928,
5332332327550844928,
5332332327550844928];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
sample_02_images,
sample_02_hashes);
// 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] = [6917529027641081856,
6917529027641081856,
6917529027641081856];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
sample_03_images,
sample_03_hashes);
// 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")];
let sample_04_hashes: [u64; 3] = [10997931646002397184,
10997931646002397184,
11142046834078253056];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
sample_04_images,
sample_04_hashes);
// Clean_Cache
// super::teardown();
}
}

11
src/main.rs

@ -42,7 +42,7 @@ fn main() {
let args: Args = Docopt::new(USAGE) let args: Args = Docopt::new(USAGE)
.and_then(|d| d.decode()) .and_then(|d| d.decode())
.unwrap_or_else(|e| e.exit()); .unwrap_or_else(|e| e.exit());
// Print version information and exit // Print version information and exit
if args.flag_version { if args.flag_version {
println!("Perceptual Image Hashing: v{}", VERSION); println!("Perceptual Image Hashing: v{}", VERSION);
@ -66,11 +66,10 @@ fn main() {
dhash: {} dhash: {}
phash: {} phash: {}
"#, "#,
hashes.orig_path,
hashes.ahash,
hashes.dhash,
hashes.phash
);
hashes.orig_path,
hashes.ahash,
hashes.dhash,
hashes.phash);
println!("{}", hash_result); println!("{}", hash_result);
} }
// Otherwise process only specific hashes // Otherwise process only specific hashes

Loading…
Cancel
Save