Browse Source

Rustfmt and code cleanup

develop
Drew Short 7 years ago
parent
commit
487401a45a
  1. 17
      src/cache.rs
  2. 4
      src/hash/ahash.rs
  3. 4
      src/hash/dhash.rs
  4. 18
      src/hash/mod.rs
  5. 29
      src/hash/phash.rs
  6. 60
      src/lib.rs
  7. 16
      src/main.rs

17
src/cache.rs

@ -253,11 +253,10 @@ impl<'a> Cache<'a> {
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)
});
let mut row_str =
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);
@ -319,14 +318,12 @@ impl<'a> Cache<'a> {
}
};
// convert the matrix
let matrix: Vec<Vec<f64>> = matrix_data_str.trim()
let matrix: Vec<Vec<f64>> = matrix_data_str
.trim()
.split("\n")
.map(|line| {
line.split(",")
.map(|f| {
f64::from_str(f)
.unwrap()
})
.map(|f| f64::from_str(f).unwrap())
.collect()
})
.collect();

4
src/hash/ahash.rs

@ -60,8 +60,8 @@ impl<'a> PerceptualHash for AHash<'a> {
}
// println!("Hash for {} is {}", prepared_image.orig_path, hash);
hash
},
None => 0u64
}
None => 0u64,
}
}
}

4
src/hash/dhash.rs

@ -61,8 +61,8 @@ impl<'a> PerceptualHash for DHash<'a> {
}
hash
},
None => 0u64
}
None => 0u64,
}
}
}

18
src/hash/mod.rs

@ -59,9 +59,12 @@ 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 {
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
@ -155,13 +158,13 @@ pub fn prepare_image<'a>(path: &'a Path,
Ok(_) => {}
Err(e) => println!("Unable to store image in cache. {}", e),
};
},
}
None => {}
};
processed_image
}
}
},
}
None => process_image(&image_path, size),
}
}
@ -169,15 +172,14 @@ pub fn prepare_image<'a>(path: &'a Path,
/**
* Turn the image into something we can work with
*/
fn process_image<'a>(image_path: &'a str,
size: u32) -> PreparedImage<'a> {
fn process_image<'a>(image_path: &'a str, size: u32) -> PreparedImage<'a> {
// Otherwise let's do that work now and store it.
//println!("Path: {}", image_path);
let image = match image::open(Path::new(image_path)) {
Ok(image) => {
let small_image = image.resize_exact(size, size, FilterType::Lanczos3);
Some(small_image.to_luma())
},
}
Err(e) => {
println!("Error Processing Image [{}]: {} ", image_path, e);
None

29
src/hash/phash.rs

@ -44,20 +44,23 @@ impl<'a> PerceptualHash for PHash<'a> {
// Atleast compared to opening and processing the images
let data_matrix: Vec<Vec<f64>> = 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);
// Store this DFT in the cache
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),
};
matrix
}
}
},
None => create_data_matrix(width, height, &image)
}
None => create_data_matrix(width, height, &image),
};
// Only need the top left quadrant
@ -78,27 +81,26 @@ impl<'a> PerceptualHash for PHash<'a> {
// Calculating a hash based on the mean
let mut hash = 0u64;
for x in 0..target_width {
// println!("Mean: {} Values: {:?}",mean,data_matrix[x]);
for y in 0..target_height {
if data_matrix[x][y] >= mean {
hash |= 1;
// println!("Pixel {} is >= {} therefore {:b}", pixel_sum, mean, hash);
} else {
hash |= 0;
// println!("Pixel {} is < {} therefore {:b}", pixel_sum, mean, hash);
}
hash <<= 1;
}
}
// println!("Hash for {} is {}", prepared_image.orig_path, hash);
hash
},
None => 0u64
}
None => 0u64,
}
}
}
fn create_data_matrix(width: usize, height: usize, image: &super::image::ImageBuffer<super::image::Luma<u8>, Vec<u8>>) -> Vec<Vec<f64>> {
fn create_data_matrix(width: usize,
height: usize,
image: &super::image::ImageBuffer<super::image::Luma<u8>, Vec<u8>>)
-> Vec<Vec<f64>> {
let mut data_matrix: Vec<Vec<f64>> = Vec::new();
// Preparing the results
for x in 0..width {
@ -106,10 +108,7 @@ fn create_data_matrix(width: usize, height: usize, image: &super::image::ImageBu
for y in 0..height {
let pos_x = x as u32;
let pos_y = y as u32;
data_matrix[x]
.push(image
.get_pixel(pos_x, pos_y)
.channels()[0] as f64);
data_matrix[x].push(image.get_pixel(pos_x, pos_y).channels()[0] as f64);
}
}

60
src/lib.rs

@ -20,17 +20,21 @@ use cache::Cache;
#[repr(C)]
pub struct PIHash<'a> {
cache: Option<Cache<'a>>
cache: Option<Cache<'a>>,
}
impl<'a> PIHash<'a> {
/**
* Create a new pihash library, and initialize a cache of a path is passed. If none is passed then no cache is initialized or used with the library
* Create a new pihash library, and initialize a cache of a path is passed.
* If none is passed then no cache is initialized or used with the library
*/
pub fn new(cache_path: Option<&'a str>) -> PIHash<'a> {
match cache_path {
Some(path) => {
let cache = Cache { cache_dir: path, use_cache: true};
let cache = Cache {
cache_dir: path,
use_cache: true,
};
match cache.init() {
Ok(_) => PIHash { cache: Some(cache) },
Err(e) => {
@ -38,12 +42,16 @@ impl<'a> PIHash<'a> {
PIHash { cache: None }
}
}
},
}
None => PIHash { cache: None },
}
}
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)
}
@ -172,7 +180,7 @@ fn to_hex_string(bytes: &[u8]) -> String {
// Module for the tests
//
#[cfg(test)]
#[cfg(test)]
mod tests {
use std::fs;
@ -194,11 +202,11 @@ mod tests {
Some(_) => {
if ext.unwrap() == "jpg" {
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;
}
}
@ -221,14 +229,12 @@ mod tests {
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);
let calculated_hash = lib.get_perceptual_hash(&image_path, &hash_precision, &hash_type);
println!("Image hashes for [{}] expected: [{}] actual: [{}]",
image_path.to_str().unwrap(),
image_hashes[index],
calculated_hash);
assert_eq!(calculated_hash,image_hashes[index]);
assert_eq!(calculated_hash, image_hashes[index]);
hashes[index] = calculated_hash;
}
@ -258,9 +264,7 @@ 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,
857051992374038];
let sample_01_hashes: [u64; 3] = [857051991849750, 857051991849750, 857051992374038];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
1u64,
@ -286,9 +290,8 @@ mod 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];
let sample_03_hashes: [u64; 3] =
[135670932300497406, 135670932300497406, 135670932300497406];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
1u64,
@ -351,9 +354,8 @@ mod 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] = [262683193365159876,
225528496439353284,
225528496435158982];
let sample_03_hashes: [u64; 3] =
[262683193365159876, 225528496439353284, 225528496435158982];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
4u64,
@ -388,9 +390,7 @@ 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];
let sample_01_hashes: [u64; 3] = [72357778504597504, 72357778504597504, 72357778504597504];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
0u64,
@ -452,11 +452,15 @@ 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);
})
}
@ -468,7 +472,9 @@ 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);
})
}
}

16
src/main.rs

@ -63,7 +63,10 @@ fn main() {
let mut comparison_hashes: Vec<pihash::hash::PerceptualHashes> = 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();
@ -102,7 +105,10 @@ fn flags_get_all_perceptual_hashes(args: &Args) -> bool {
(!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 {
@ -121,8 +127,10 @@ fn get_requested_perceptual_hashes<'a>(lib: &pihash::PIHash, image_path: &'a Pat
0u64
};
pihash::hash::PerceptualHashes {orig_path: image_path.to_str().unwrap(),
pihash::hash::PerceptualHashes {
orig_path: image_path.to_str().unwrap(),
ahash: ahash,
dhash: dhash,
phash: phash}
phash: phash,
}
}
Loading…
Cancel
Save