Browse Source

Style changes

Changed the repo to ignore the rs.bk files produced by rustfmt
Ran RustFmt on the repository to cleanup the code
develop
Drew Short 9 years ago
parent
commit
0d128cb8aa
  1. 3
      .gitignore
  2. 56
      src/cache.rs
  3. 99
      src/hash.rs
  4. 221
      src/lib.rs
  5. 25
      src/main.rs

3
.gitignore

@ -22,3 +22,6 @@ Cargo.lock
# Ignore sublime workspace files # Ignore sublime workspace files
*.sublime-workspace *.sublime-workspace
#Rustfmt backup files
*.rs.bk

56
src/cache.rs

@ -46,14 +46,19 @@ pub fn put_image_in_cache(path: &Path, size: u32, image: &ImageBuffer<image::Lum
let hash = get_file_hash(&path); let hash = get_file_hash(&path);
match hash { match hash {
Ok(sha1) => { Ok(sha1) => {
let cache_path_str = format!("{}/{}x{}_{}.{}",CACHE_DIR, size, size, sha1, CACHE_FILE_EXT);
let cache_path_str = format!("{}/{}x{}_{}.{}",
CACHE_DIR,
size,
size,
sha1,
CACHE_FILE_EXT);
let cached_path = Path::new(&cache_path_str); let cached_path = Path::new(&cache_path_str);
// Save the file into the cache // Save the file into the cache
match image.save(cached_path) { match image.save(cached_path) {
Ok(_) => {},
Ok(_) => {}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
},
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -61,7 +66,10 @@ pub fn put_image_in_cache(path: &Path, size: u32, image: &ImageBuffer<image::Lum
/** /**
* 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(path: &Path, size: u32, extension: &str, file_contents: &Vec<Vec<f64>>) {
pub fn put_matrix_in_cache(path: &Path,
size: u32,
extension: &str,
file_contents: &Vec<Vec<f64>>) {
let hash = get_file_hash(&path); let hash = get_file_hash(&path);
match hash { match hash {
Ok(sha1) => { Ok(sha1) => {
@ -71,7 +79,8 @@ pub fn put_matrix_in_cache(path: &Path, size: u32, extension: &str, file_content
match File::create(&cached_path) { match File::create(&cached_path) {
Ok(mut file) => { Ok(mut file) => {
for row in file_contents { for row in file_contents {
let mut row_str = row.iter().fold(String::new(), |acc, &item| acc + &format!("{},",item));
let mut row_str = row.iter().fold(String::new(),
|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);
@ -79,10 +88,10 @@ pub fn put_matrix_in_cache(path: &Path, size: u32, extension: &str, file_content
file.write(&row_str.into_bytes()); file.write(&row_str.into_bytes());
} }
file.flush(); file.flush();
},
Err(_) => {},
} }
},
Err(_) => {}
}
}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -90,30 +99,35 @@ pub fn put_matrix_in_cache(path: &Path, size: u32, extension: &str, file_content
/** /**
* Get an image buffer out of the cache * Get an image buffer out of the cache
*/ */
pub fn get_image_from_cache(path: &Path, size: u32) -> Option<ImageBuffer<image::Luma<u8>, Vec<u8>>> {
pub fn get_image_from_cache(path: &Path,
size: u32)
-> Option<ImageBuffer<image::Luma<u8>, Vec<u8>>> {
let hash = get_file_hash(&path); let hash = 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!("{}/{}x{}_{}.{}",CACHE_DIR, size, size, sha1, CACHE_FILE_EXT);
let cache_path_str = format!("{}/{}x{}_{}.{}",
CACHE_DIR,
size,
size,
sha1,
CACHE_FILE_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) {
Ok(_) => { Ok(_) => {
let image = image::open(&cached_path).unwrap(); let image = image::open(&cached_path).unwrap();
Some(image.to_luma()) Some(image.to_luma())
},
}
// Don't really care here, it just means an existing cached // Don't really care here, it just means an existing cached
// file doesn't exist, or can't be read. // file doesn't exist, or can't be read.
Err(_) => {
None
},
Err(_) => None,
}
} }
},
Err(e) => { Err(e) => {
println!("Error: {}", e); println!("Error: {}", e);
None None
},
}
} }
} }
@ -136,18 +150,16 @@ pub fn get_matrix_from_cache(path: &Path, size: u32, extension: &str) -> Option<
let matrix_data_str = String::from_utf8(matrix_data); let matrix_data_str = String::from_utf8(matrix_data);
// convert the matrix // convert the matrix
Some(matrix) Some(matrix)
},
}
// Don't really care here, it just means an existing cached // Don't really care here, it just means an existing cached
// file doesn't exist, or can't be read. // file doesn't exist, or can't be read.
Err(_) => {
None
},
Err(_) => None,
}
} }
},
Err(e) => { Err(e) => {
println!("Error: {}", e); println!("Error: {}", e);
None None
},
}
} }
} }

99
src/hash.rs

@ -10,11 +10,7 @@ extern crate complex;
use std::path::Path; use std::path::Path;
use std::f64; use std::f64;
use self::image::{
GenericImage,
Pixel,
FilterType
};
use self::image::{GenericImage, Pixel, FilterType};
use self::dft::Transform; use self::dft::Transform;
use cache; use cache;
@ -40,7 +36,7 @@ const FLOAT_PRECISION_MIN_5: f64 = f64::MIN / 100000_f64;
*/ */
pub struct PreparedImage<'a> { pub struct PreparedImage<'a> {
orig_path: &'a str, orig_path: &'a str,
image: image::ImageBuffer<image::Luma<u8>,Vec<u8>>
image: image::ImageBuffer<image::Luma<u8>, Vec<u8>>,
} }
/** /**
@ -50,7 +46,7 @@ pub struct PerceptualHashes<'a> {
pub orig_path: &'a str, pub orig_path: &'a str,
pub ahash: u64, pub ahash: u64,
pub dhash: u64, pub dhash: u64,
pub phash: u64
pub phash: u64,
} }
/** /**
@ -66,9 +62,8 @@ pub enum Precision {
High, High,
} }
/*
* Get the size of the required image
*/
// Get the size of the required image
//
impl Precision { impl Precision {
fn get_size(&self) -> u32 { fn get_size(&self) -> u32 {
match *self { match *self {
@ -85,7 +80,7 @@ impl Precision {
pub enum HashType { pub enum HashType {
Ahash, Ahash,
Dhash, Dhash,
Phash
Phash,
} }
/** /**
@ -102,25 +97,34 @@ pub enum HashType {
* A PreparedImage struct with the required information for performing hashing * A PreparedImage struct with the required information for performing hashing
* *
*/ */
pub fn prepare_image<'a>(path: &'a Path, hash_type: &HashType, precision: &Precision) -> PreparedImage<'a> {
pub fn prepare_image<'a>(path: &'a Path,
hash_type: &HashType,
precision: &Precision)
-> PreparedImage<'a> {
let image_path = path.to_str().unwrap(); let image_path = path.to_str().unwrap();
let size: u32 = match *hash_type { let size: u32 = match *hash_type {
HashType::Phash => precision.get_size() * 4, HashType::Phash => precision.get_size() * 4,
_ => precision.get_size()
_ => precision.get_size(),
}; };
// Check if we have the already converted image in a cache and use that if possible. // Check if we have the already converted image in a cache and use that if possible.
match cache::get_image_from_cache(&path, size) { match cache::get_image_from_cache(&path, size) {
Some(image) => { Some(image) => {
PreparedImage { orig_path: &*image_path, image: image }
},
PreparedImage {
orig_path: &*image_path,
image: image,
}
}
None => { None => {
// Otherwise let's do that work now and store it. // Otherwise let's do that work now and store it.
let image = image::open(path).unwrap(); let image = image::open(path).unwrap();
let small_image = image.resize_exact(size, size, FilterType::Lanczos3); let small_image = image.resize_exact(size, size, FilterType::Lanczos3);
let grey_image = small_image.to_luma(); let grey_image = small_image.to_luma();
cache::put_image_in_cache(&path, size, &grey_image); cache::put_image_in_cache(&path, size, &grey_image);
PreparedImage { orig_path: &*image_path, image: grey_image }
},
PreparedImage {
orig_path: &*image_path,
image: grey_image,
}
}
} }
} }
@ -132,7 +136,12 @@ pub fn get_perceptual_hashes<'a>(path: &'a Path, precision: &Precision) -> Perce
let ahash = AHash::new(&path, &precision).get_hash(); let ahash = AHash::new(&path, &precision).get_hash();
let dhash = DHash::new(&path, &precision).get_hash(); let dhash = DHash::new(&path, &precision).get_hash();
let phash = PHash::new(&path, &precision).get_hash(); let phash = PHash::new(&path, &precision).get_hash();
PerceptualHashes { orig_path: &*image_path, ahash: ahash, dhash: dhash, phash: phash }
PerceptualHashes {
orig_path: &*image_path,
ahash: ahash,
dhash: dhash,
phash: phash,
}
} }
/** /**
@ -148,7 +157,7 @@ pub fn calculate_hamming_distance(hash1: u64, hash2: u64) -> u64 {
for bit in bin_diff_str.chars() { for bit in bin_diff_str.chars() {
match bit { match bit {
'1' => hamming += 1, '1' => hamming += 1,
_ => continue
_ => continue,
} }
} }
hamming hamming
@ -291,14 +300,18 @@ impl<'a> PerceptualHash for PHash<'a> {
for y in 0..height { for y in 0..height {
let pos_x = x as u32; let pos_x = x as u32;
let pos_y = y as u32; let pos_y = y as u32;
data_matrix[x].push(self.prepared_image.image.get_pixel(pos_x,pos_y).channels()[0] as f64);
data_matrix[x]
.push(self.prepared_image.image.get_pixel(pos_x, pos_y).channels()[0] as f64);
} }
} }
// 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
cache::put_matrix_in_cache(&Path::new(self.prepared_image.orig_path),width as u32,&"dft",&data_matrix);
cache::put_matrix_in_cache(&Path::new(self.prepared_image.orig_path),
width as u32,
&"dft",
&data_matrix);
// Only need the top left quadrant // Only need the top left quadrant
let target_width = (width / 4) as usize; let target_width = (width / 4) as usize;
@ -335,21 +348,20 @@ impl<'a> PerceptualHash for PHash<'a> {
} }
} }
/*
* Use a 1D DFT to cacluate the 2D DFT.
*
* This is achieved by calculating the DFT for each row, then calculating the
* DFT for each column of DFT row data. This means that a 32x32 image with have
* 1024 1D DFT operations performed on it. (Slightly caclulation intensive)
*
* This operation is in place on the data in the provided vector
*
* Inspired by:
* http://www.inf.ufsc.br/~visao/khoros/html-dip/c5/s2/front-page.html
*
* Checked with:
* http://calculator.vhex.net/post/calculator-result/2d-discrete-fourier-transform
*/
// Use a 1D DFT to cacluate the 2D DFT.
//
// This is achieved by calculating the DFT for each row, then calculating the
// DFT for each column of DFT row data. This means that a 32x32 image with have
// 1024 1D DFT operations performed on it. (Slightly caclulation intensive)
//
// This operation is in place on the data in the provided vector
//
// Inspired by:
// http://www.inf.ufsc.br/~visao/khoros/html-dip/c5/s2/front-page.html
//
// Checked with:
// http://calculator.vhex.net/post/calculator-result/2d-discrete-fourier-transform
//
fn calculate_2d_dft(data_matrix: &mut Vec<Vec<f64>>) { fn calculate_2d_dft(data_matrix: &mut Vec<Vec<f64>>) {
// println!("{:?}", data_matrix); // println!("{:?}", data_matrix);
let width = data_matrix.len(); let width = data_matrix.len();
@ -395,20 +407,15 @@ fn calculate_2d_dft(data_matrix: &mut Vec<Vec<f64>>){
fn round_float(f: f64) -> f64 { fn round_float(f: f64) -> f64 {
if f >= FLOAT_PRECISION_MAX_1 || f <= FLOAT_PRECISION_MIN_1 { if f >= FLOAT_PRECISION_MAX_1 || f <= FLOAT_PRECISION_MIN_1 {
f f
}
else if f >= FLOAT_PRECISION_MAX_2 || f <= FLOAT_PRECISION_MIN_2 {
} else if f >= FLOAT_PRECISION_MAX_2 || f <= FLOAT_PRECISION_MIN_2 {
(f * 10_f64).round() / 10_f64 (f * 10_f64).round() / 10_f64
}
else if f >= FLOAT_PRECISION_MAX_3 || f <= FLOAT_PRECISION_MIN_3 {
} else if f >= FLOAT_PRECISION_MAX_3 || f <= FLOAT_PRECISION_MIN_3 {
(f * 100_f64).round() / 100_f64 (f * 100_f64).round() / 100_f64
}
else if f >= FLOAT_PRECISION_MAX_4 || f <= FLOAT_PRECISION_MIN_4 {
} else if f >= FLOAT_PRECISION_MAX_4 || f <= FLOAT_PRECISION_MIN_4 {
(f * 1000_f64).round() / 1000_f64 (f * 1000_f64).round() / 1000_f64
}
else if f >= FLOAT_PRECISION_MAX_5 || f <= FLOAT_PRECISION_MIN_5 {
} else if f >= FLOAT_PRECISION_MAX_5 || f <= FLOAT_PRECISION_MIN_5 {
(f * 10000_f64).round() / 10000_f64 (f * 10000_f64).round() / 10000_f64
}
else {
} else {
(f * 100000_f64).round() / 100000_f64 (f * 100000_f64).round() / 100000_f64
} }
} }

221
src/lib.rs

@ -16,7 +16,7 @@ use hash::PerceptualHash;
*/ */
pub fn init() { pub fn init() {
match cache::prep_cache() { match cache::prep_cache() {
Ok(_) => {},
Ok(_) => {}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -26,7 +26,7 @@ pub fn init() {
*/ */
pub fn teardown() { pub fn teardown() {
match cache::clear_cache() { match cache::clear_cache() {
Ok(_) => {},
Ok(_) => {}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
@ -51,9 +51,8 @@ pub fn get_hamming_distance(hash1: u64, hash2: u64) -> u64 {
hash::calculate_hamming_distance(hash1, hash2) hash::calculate_hamming_distance(hash1, hash2)
} }
/*
* Module for the tests
*/
// Module for the tests
//
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
@ -75,10 +74,10 @@ mod tests {
num_paths += 1; num_paths += 1;
println!("Is a image {}: {:?}", num_paths, orig_path) ; println!("Is a image {}: {:?}", num_paths, orig_path) ;
} }
},
}
_ => { _ => {
println!("Not an image: {:?}", orig_path) ; println!("Not an image: {:?}", orig_path) ;
continue
continue;
} }
} }
// println!("Name: {}", path.unwrap().path().display()) // println!("Name: {}", path.unwrap().path().display())
@ -89,8 +88,7 @@ mod tests {
// Simple function for the unit tests to succinctly test a set of images // Simple function for the unit tests to succinctly test a set of images
// that are organized in the fashion of large->medium->small // that are organized in the fashion of large->medium->small
fn test_imageset_hash(
large_phash: &hash::PerceptualHash,
fn test_imageset_hash(large_phash: &hash::PerceptualHash,
medium_phash: &hash::PerceptualHash, medium_phash: &hash::PerceptualHash,
small_phash: &hash::PerceptualHash, small_phash: &hash::PerceptualHash,
expected_large_hash: u64, expected_large_hash: u64,
@ -105,17 +103,32 @@ mod tests {
let actual_small_hash = small_phash.get_hash(); let actual_small_hash = small_phash.get_hash();
// println for the purpose of debugging // println for the purpose of debugging
println!("Large Image: expected: {} actual: {}", expected_large_hash, actual_large_hash);
println!("Medium Image: expected: {} actual: {}", expected_medium_hash, actual_medium_hash);
println!("Small Image: expected: {} actual: {}", expected_small_hash, actual_small_hash);
let actual_large_medium_hamming = hash::calculate_hamming_distance(actual_large_hash, actual_medium_hash);
let actual_large_small_hamming = hash::calculate_hamming_distance(actual_large_hash, actual_small_hash);
let actual_medium_small_hamming = hash::calculate_hamming_distance(actual_medium_hash, actual_small_hash);
println!("Large-Medium Hamming Distance: expected: {} actual: {}", expected_large_medium_hamming, actual_large_medium_hamming);
println!("Large-Small Hamming Distance: expected: {} actual: {}", expected_large_small_hamming, actual_large_small_hamming);
println!("Medium-Small Hamming Distance: expected: {} actual: {}", expected_medium_small_hamming, actual_medium_small_hamming);
println!("Large Image: expected: {} actual: {}",
expected_large_hash,
actual_large_hash);
println!("Medium Image: expected: {} actual: {}",
expected_medium_hash,
actual_medium_hash);
println!("Small Image: expected: {} actual: {}",
expected_small_hash,
actual_small_hash);
let actual_large_medium_hamming = hash::calculate_hamming_distance(actual_large_hash,
actual_medium_hash);
let actual_large_small_hamming = hash::calculate_hamming_distance(actual_large_hash,
actual_small_hash);
let actual_medium_small_hamming = hash::calculate_hamming_distance(actual_medium_hash,
actual_small_hash);
println!("Large-Medium Hamming Distance: expected: {} actual: {}",
expected_large_medium_hamming,
actual_large_medium_hamming);
println!("Large-Small Hamming Distance: expected: {} actual: {}",
expected_large_small_hamming,
actual_large_small_hamming);
println!("Medium-Small Hamming Distance: expected: {} actual: {}",
expected_medium_small_hamming,
actual_medium_small_hamming);
// Doing that asserts // Doing that asserts
assert!(actual_large_hash == expected_large_hash); assert!(actual_large_hash == expected_large_hash);
@ -134,55 +147,63 @@ mod tests {
super::init(); super::init();
// Sample_01 tests // Sample_01 tests
test_imageset_hash(
&hash::AHash::new(path::Path::new("./test_images/sample_01_large.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_01_medium.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium),
857051991849750, 857051991849750,
857051991849750, 857051991849750,
857051991849750, 857051991849750,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_02 tests // Sample_02 tests
test_imageset_hash(
&hash::AHash::new(path::Path::new("./test_images/sample_02_large.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_02_medium.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium),
18446744073441116160, 18446744073441116160,
18446744073441116160, 18446744073441116160,
18446744073441116160, 18446744073441116160,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(
&hash::AHash::new(path::Path::new("./test_images/sample_03_large.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_03_medium.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium),
135670932300497406, 135670932300497406,
135670932300497406, 135670932300497406,
135670932300497406, 135670932300497406,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_04 tests // Sample_04 tests
test_imageset_hash(
&hash::AHash::new(path::Path::new("./test_images/sample_04_large.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_04_medium.jpg"), &hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"),
&hash::Precision::Medium),
&hash::AHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium),
18446460933225054208, 18446460933225054208,
18446460933090836480, 18446460933090836480,
18446460933090836480, 18446460933090836480,
1u64, 1u64,
1u64, 1u64,
0u64
);
0u64);
// Clean_Cache // Clean_Cache
// super::teardown(); // super::teardown();
@ -194,55 +215,63 @@ mod tests {
super::init(); super::init();
// Sample_01 tests // Sample_01 tests
test_imageset_hash(
&hash::DHash::new(path::Path::new("./test_images/sample_01_large.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_01_medium.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium),
7937395827556495926, 7937395827556495926,
7937395827556495926, 7937395827556495926,
7939647627370181174, 7939647627370181174,
0u64, 0u64,
1u64, 1u64,
1u64
);
1u64);
// Sample_02 tests // Sample_02 tests
test_imageset_hash(
&hash::DHash::new(path::Path::new("./test_images/sample_02_large.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_02_medium.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium),
11009829669713008949, 11009829669713008949,
11009829670249879861, 11009829670249879861,
11009829669713008949, 11009829669713008949,
1u64, 1u64,
0u64, 0u64,
1u64
);
1u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(
&hash::DHash::new(path::Path::new("./test_images/sample_03_large.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_03_medium.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium),
225528496439353286, 225528496439353286,
225528496439353286, 225528496439353286,
226654396346195908, 226654396346195908,
0u64, 0u64,
2u64, 2u64,
2u64
);
2u64);
// Sample_04 tests // Sample_04 tests
test_imageset_hash(
&hash::DHash::new(path::Path::new("./test_images/sample_04_large.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_04_medium.jpg"), &hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"),
&hash::Precision::Medium),
&hash::DHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium),
14620651386429567209, 14620651386429567209,
14620651386429567209, 14620651386429567209,
14620651386429567209, 14620651386429567209,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Clean_Cache // Clean_Cache
// super::teardown(); // super::teardown();
@ -254,55 +283,63 @@ mod tests {
super::init(); super::init();
// Sample_01 tests // Sample_01 tests
test_imageset_hash(
&hash::PHash::new(path::Path::new("./test_images/sample_01_large.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_01_medium.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium),
72357778504597504, 72357778504597504,
72357778504597504, 72357778504597504,
72357778504597504, 72357778504597504,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_02 tests // Sample_02 tests
test_imageset_hash(
&hash::PHash::new(path::Path::new("./test_images/sample_02_large.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_02_medium.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium),
5332332327550844928, 5332332327550844928,
5332332327550844928, 5332332327550844928,
5332332327550844928, 5332332327550844928,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(
&hash::PHash::new(path::Path::new("./test_images/sample_03_large.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_03_medium.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium),
6917529027641081856, 6917529027641081856,
6917529027641081856, 6917529027641081856,
6917529027641081856, 6917529027641081856,
0u64, 0u64,
0u64, 0u64,
0u64
);
0u64);
// Sample_04 tests // Sample_04 tests
test_imageset_hash(
&hash::PHash::new(path::Path::new("./test_images/sample_04_large.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_04_medium.jpg"), &hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::Precision::Medium),
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"),
&hash::Precision::Medium),
&hash::PHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium),
10997931646002397184, 10997931646002397184,
10997931646002397184, 10997931646002397184,
11142046834078253056, 11142046834078253056,
0u64, 0u64,
1u64, 1u64,
1u64
);
1u64);
// Clean_Cache // Clean_Cache
// super::teardown(); // super::teardown();

25
src/main.rs

@ -15,15 +15,20 @@ const USAGE: &'static str = "
Perceptual Image Hashing (pihash) Perceptual Image Hashing (pihash)
Usage: Usage:
pihash [options] <path>...
pihash [options] \
<path>...
pihash (--help | --version) pihash (--help | --version)
Options: Options:
-h, --help Show this screen.
-h, --help \
Show this screen.
-V, --version Print version. -V, --version Print version.
-a, --ahash Include an ahash calculation.
-d, --dhash Include an dhash calculation.
-p, --phash Include an phash calculation.
-a, \
--ahash Include an ahash calculation.
-d, --dhash \
Include an dhash calculation.
-p, --phash Include an phash \
calculation.
"; ";
#[derive(Debug, RustcDecodable)] #[derive(Debug, RustcDecodable)]
@ -43,8 +48,8 @@ fn main() {
// println!("{:?}", args); // println!("{:?}", args);
// All flags set or, no flags set // All flags set or, no flags set
if (args.flag_ahash && args.flag_dhash && args.flag_phash)
|| (!args.flag_ahash && !args.flag_dhash && !args.flag_phash) {
if (args.flag_ahash && args.flag_dhash && args.flag_phash) ||
(!args.flag_ahash && !args.flag_dhash && !args.flag_phash) {
for path in args.arg_path { for path in args.arg_path {
let image_path = Path::new(&path); let image_path = Path::new(&path);
let hashes = pihash::get_phashes(&image_path); let hashes = pihash::get_phashes(&image_path);
@ -53,7 +58,11 @@ fn main() {
ahash: {} ahash: {}
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