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 10 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