Browse Source

Remove lifetimes and internalize copies of strings

* Broke testing out into more distinct tests
master
Drew Short 5 years ago
parent
commit
8076a5281f
  1. 3
      FFI-tests/ffi_test.py
  2. 37
      src/cache.rs
  3. 10
      src/hash/ahash.rs
  4. 10
      src/hash/dhash.rs
  5. 49
      src/hash/mod.rs
  6. 14
      src/hash/phash.rs
  7. 252
      src/lib.rs
  8. 22
      src/main.rs

3
FFI-tests/ffi_test.py

@ -51,6 +51,7 @@ class PIHashes(Structure):
# Setting the ctypes return type references for the foreign functions
# returns a pointer to the library that we'll need to pass to all function calls
lib.ext_init.restype = c_void_p
lib.ext_init.argtypes = [c_char_p]
# Returns a longlong hash, takes a pointer and a string
lib.ext_get_ahash.restype = c_ulonglong
lib.ext_get_ahash.argtypes = [c_void_p, c_char_p]
@ -65,7 +66,7 @@ lib.ext_free_phashes.argtypes = [c_void_p]
lib.ext_free.argtypes = [c_void_p]
#initialize the library
lib_struct = lib.ext_init("./.hash_cache".encode(encoding="utf-8"))
lib_struct = lib.ext_init("./.hash_cache".encode('utf-8'))
#print("Pointer to lib_struct: ", lib_struct)

37
src/cache.rs

@ -58,26 +58,26 @@ impl PartialEq<CacheMetadata> for CacheMetadata {
* Structure to hold implementation of the cache
*/
#[repr(C)]
pub struct Cache<'a> {
pub cache_dir: &'a str,
pub struct Cache {
pub cache_dir: String,
pub use_cache: bool,
}
impl<'a> Default for Cache<'a> {
fn default() -> Cache<'a> {
impl Default for Cache {
fn default() -> Cache {
Cache {
cache_dir: DEFAULT_CACHE_DIR,
cache_dir: String::from(DEFAULT_CACHE_DIR),
use_cache: true,
}
}
}
impl<'a> Cache<'a> {
impl Cache {
/**
* Create the required directories for the cache
*/
pub fn init(&self) -> Result<(), Error> {
match create_dir_all(self.cache_dir) {
match create_dir_all(&self.cache_dir) {
Ok(_) => {
let metadata_path_str = format!("{}/{}", self.cache_dir, CACHE_METADATA_FILE);
let metadata_path = Path::new(&metadata_path_str);
@ -97,8 +97,8 @@ impl<'a> Cache<'a> {
// If they match, continue
if current_metadata != loaded_metadata {
// If they don't wipe the cache to start new
match remove_dir_all(self.cache_dir) {
Ok(_) => match create_dir_all(self.cache_dir) {
match remove_dir_all(&self.cache_dir) {
Ok(_) => match create_dir_all(&self.cache_dir) {
Ok(_) => (),
Err(e) => println!("Error: {}", e),
},
@ -130,7 +130,7 @@ impl<'a> Cache<'a> {
* Clean the cache directory completely
*/
pub fn clean(&self) -> Result<(), Error> {
remove_dir_all(self.cache_dir)
remove_dir_all(&self.cache_dir)
}
/**
@ -170,8 +170,11 @@ impl<'a> Cache<'a> {
);
let cache_dir_str =
format!("{}/image/{}x{}/{}", self.cache_dir, size, size, &sha1[..10]);
// println!("Saving: {}", cache_path_str);
match create_dir_all(cache_dir_str) {
println!("Test");
println!("{}", DEFAULT_CACHE_DIR);
println!("{}", &self.cache_dir);
// println!("Saving: {}", &cache_path_str);
match create_dir_all(&cache_dir_str) {
Ok(_) => {
let file_path = Path::new(&cache_path_str);
match File::create(file_path) {
@ -185,10 +188,16 @@ impl<'a> Cache<'a> {
}
}
}
Err(e) => return Err(e),
Err(e) => {
println!("Unable to create file {:?}", file_path);
return Err(e);
}
}
}
Err(e) => return Err(e),
Err(e) => {
println!("Unable to create directory {:?}", &cache_dir_str);
return Err(e);
}
}
}
Err(e) => {

10
src/hash/ahash.rs

@ -11,19 +11,19 @@ use super::{HashType, PerceptualHash, Precision, PreparedImage};
use super::image::GenericImageView;
pub struct AHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
pub struct AHash {
prepared_image: Box<PreparedImage>,
}
impl<'a> AHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &Option<Cache>) -> Self {
impl AHash {
pub fn new(path: &Path, precision: &Precision, cache: &Option<Cache>) -> Self {
AHash {
prepared_image: Box::new(prepare_image(&path, &HashType::AHash, &precision, cache)),
}
}
}
impl<'a> PerceptualHash for AHash<'a> {
impl PerceptualHash for AHash {
/**
* Calculate the ahash of the provided prepared image.
*

10
src/hash/dhash.rs

@ -11,19 +11,19 @@ use super::{HashType, PerceptualHash, Precision, PreparedImage};
use super::image::GenericImageView;
pub struct DHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
pub struct DHash {
prepared_image: Box<PreparedImage>,
}
impl<'a> DHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &Option<Cache>) -> Self {
impl DHash {
pub fn new(path: &Path, precision: &Precision, cache: &Option<Cache>) -> Self {
DHash {
prepared_image: Box::new(prepare_image(&path, &HashType::DHash, &precision, cache)),
}
}
}
impl<'a> PerceptualHash for DHash<'a> {
impl PerceptualHash for DHash {
/**
* Calculate the dhash of the provided prepared image
*

49
src/hash/mod.rs

@ -6,12 +6,14 @@
extern crate dft;
extern crate image;
use self::image::FilterType;
use cache::Cache;
use std::f64;
use std::fmt;
use std::path::Path;
use cache::Cache;
use self::image::FilterType;
mod ahash;
mod dhash;
mod phash;
@ -42,23 +44,23 @@ const HAMMING_DISTANCE_SIMILARITY_LIMIT: u64 = 5u64;
/**
* Prepared image that can be used to generate hashes
*/
pub struct PreparedImage<'a> {
orig_path: &'a str,
pub struct PreparedImage {
orig_path: String,
image: Option<image::DynamicImage>,
}
/**
* Wraps the various perceptual hashes
*/
pub struct PerceptualHashes<'a> {
pub orig_path: &'a str,
pub struct PerceptualHashes {
pub orig_path: String,
pub ahash: u64,
pub dhash: u64,
pub phash: u64,
}
impl<'a> PerceptualHashes<'a> {
pub fn similar(&self, other: &'a PerceptualHashes<'a>) -> bool {
impl PerceptualHashes {
pub fn similar(&self, other: &PerceptualHashes) -> bool {
if self.orig_path != other.orig_path
&& calculate_hamming_distance(self.ahash, other.ahash)
<= HAMMING_DISTANCE_SIMILARITY_LIMIT
@ -82,6 +84,7 @@ impl<'a> PerceptualHashes<'a> {
* High aims for 128 bit precision
*/
#[allow(dead_code)]
#[derive(Copy, Clone)]
pub enum Precision {
Low,
Medium,
@ -89,7 +92,6 @@ pub enum Precision {
}
// Get the size of the required image
//
impl Precision {
fn get_size(&self) -> u32 {
match *self {
@ -103,6 +105,7 @@ impl Precision {
/**
* Types of hashes supported
*/
#[derive(Copy, Clone)]
pub enum HashType {
AHash,
DHash,
@ -141,12 +144,12 @@ pub trait PerceptualHash {
* A PreparedImage struct with the required information for performing hashing
*
*/
pub fn prepare_image<'a>(
path: &'a Path,
pub fn prepare_image(
path: &Path,
hash_type: &HashType,
precision: &Precision,
cache: &Option<Cache>,
) -> PreparedImage<'a> {
) -> PreparedImage {
let image_path = path.to_str().unwrap();
let size: u32 = match *hash_type {
HashType::PHash => precision.get_size() * 4,
@ -154,10 +157,10 @@ pub fn prepare_image<'a>(
};
// Check if we have the already converted image in a cache and use that if possible.
match *cache {
Some(ref c) => {
match c.get_image_from_cache(&path, size) {
Some(ref cache) => {
match cache.get_image_from_cache(&path, size) {
Some(image) => PreparedImage {
orig_path: &*image_path,
orig_path: String::from(&*image_path),
image: Some(image),
},
None => {
@ -165,7 +168,7 @@ pub fn prepare_image<'a>(
// Oh, and save it in a cache
match processed_image.image {
Some(ref image) => {
match c.put_image_in_cache(&path, size, &image) {
match cache.put_image_in_cache(&path, size, &image) {
Ok(_) => {}
Err(e) => println!("Unable to store image in cache. {}", e),
};
@ -197,7 +200,7 @@ fn process_image(image_path: &str, size: u32) -> PreparedImage {
}
};
PreparedImage {
orig_path: &*image_path,
orig_path: String::from(&*image_path),
image,
}
}
@ -205,8 +208,8 @@ fn process_image(image_path: &str, size: u32) -> PreparedImage {
/**
* Get a specific HashType hash
*/
pub fn get_perceptual_hash<'a>(
path: &'a Path,
pub fn get_perceptual_hash(
path: &Path,
precision: &Precision,
hash_type: &HashType,
cache: &Option<Cache>,
@ -221,17 +224,17 @@ pub fn get_perceptual_hash<'a>(
/**
* Get all perceptual hashes for an image
*/
pub fn get_perceptual_hashes<'a>(
path: &'a Path,
pub fn get_perceptual_hashes(
path: &Path,
precision: &Precision,
cache: &Option<Cache>,
) -> PerceptualHashes<'a> {
) -> PerceptualHashes {
let image_path = path.to_str().unwrap();
let ahash = ahash::AHash::new(&path, &precision, &cache).get_hash(&cache);
let dhash = dhash::DHash::new(&path, &precision, &cache).get_hash(&cache);
let phash = phash::PHash::new(&path, &precision, &cache).get_hash(&cache);
PerceptualHashes {
orig_path: &*image_path,
orig_path: String::from(&*image_path),
ahash: ahash,
dhash: dhash,
phash: phash,

14
src/hash/phash.rs

@ -12,19 +12,19 @@ use super::image::{DynamicImage, GenericImageView, Pixel};
use super::prepare_image;
use super::{HashType, PerceptualHash, Precision, PreparedImage};
pub struct PHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
pub struct PHash {
prepared_image: Box<PreparedImage>,
}
impl<'a> PHash<'a> {
pub fn new(path: &'a Path, precision: &Precision, cache: &Option<Cache>) -> Self {
impl PHash {
pub fn new(path: &Path, precision: &Precision, cache: &Option<Cache>) -> Self {
PHash {
prepared_image: Box::new(prepare_image(&path, &HashType::PHash, &precision, cache)),
}
}
}
impl<'a> PerceptualHash for PHash<'a> {
impl PerceptualHash for PHash {
/**
* Calculate the phash of the provided prepared image
*
@ -45,14 +45,14 @@ impl<'a> PerceptualHash for PHash<'a> {
let data_matrix: Vec<Vec<f64>> = match *cache {
Some(ref c) => {
match c.get_matrix_from_cache(
&Path::new(self.prepared_image.orig_path),
&Path::new(&self.prepared_image.orig_path),
width as u32,
) {
Some(matrix) => matrix,
None => {
let matrix = create_data_matrix(width, height, &image);
match c.put_matrix_in_cache(
&Path::new(self.prepared_image.orig_path),
&Path::new(&self.prepared_image.orig_path),
width as u32,
&matrix,
) {

252
src/lib.rs

@ -20,20 +20,20 @@ pub mod cache;
pub mod hash;
#[repr(C)]
pub struct PIHash<'a> {
cache: Option<Cache<'a>>,
pub struct PIHash {
cache: Option<Cache>,
}
impl<'a> PIHash<'a> {
impl PIHash {
/**
* 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> {
pub fn new(cache_path: Option<&str>) -> PIHash {
match cache_path {
Some(path) => {
let cache = Cache {
cache_dir: path,
cache_dir: String::from(path),
use_cache: true,
};
match cache.init() {
@ -57,7 +57,7 @@ impl<'a> PIHash<'a> {
hash::get_perceptual_hash(&path, &precision, &hash_type, &self.cache)
}
pub fn get_phashes(&self, path: &'a Path) -> hash::PerceptualHashes {
pub fn get_phashes(&self, path: &Path) -> hash::PerceptualHashes {
hash::get_perceptual_hashes(&path, &hash::Precision::Medium, &self.cache)
}
@ -218,6 +218,9 @@ mod tests {
use super::test::Bencher;
use super::PIHash;
thread_local!(static LIB: PIHash = PIHash::new(Some(cache::DEFAULT_CACHE_DIR)));
thread_local!(static NO_CACHE_LIB: PIHash = PIHash::new(None));
#[test]
fn test_can_get_test_images() {
let paths = fs::read_dir(&Path::new("./test_images")).unwrap();
@ -288,37 +291,57 @@ mod tests {
}
}
#[test]
fn test_confirm_ahash_results() {
// Prep_library
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
let no_cache_lib = PIHash::new(None);
/**
* Test image set with and without caching
*/
fn test_image_set(
hash_type: hash::HashType,
hash_precision: hash::Precision,
max_hamming_distance: u64,
image_paths: [&Path; 3],
image_hashes: [u64; 3],
) {
LIB.with(|lib| {
test_imageset_hash(
hash_type,
hash_precision,
max_hamming_distance,
image_paths,
image_hashes,
lib,
);
});
NO_CACHE_LIB.with(|lib| {
test_imageset_hash(
hash_type,
hash_precision,
max_hamming_distance,
image_paths,
image_hashes,
lib,
);
});
}
// Sample_01 tests
#[test]
fn test_confirm_ahash_results_sample_01() {
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(
test_image_set(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&no_cache_lib,
);
}
// Sample_02 tests
#[test]
fn test_confirm_ahash_results_sample_02() {
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
@ -329,24 +352,17 @@ mod tests {
18446744073441116160,
18446744073441116160,
];
test_imageset_hash(
test_image_set(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&no_cache_lib,
);
}
// Sample_03 tests
#[test]
fn test_confirm_ahash_results_sample_03() {
let sample_03_images: [&Path; 3] = [
&Path::new("./test_images/sample_03_large.jpg"),
&Path::new("./test_images/sample_03_medium.jpg"),
@ -354,24 +370,17 @@ mod tests {
];
let sample_03_hashes: [u64; 3] =
[135670932300497406, 135670932300497406, 135670932300497406];
test_imageset_hash(
test_image_set(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&no_cache_lib,
);
}
// Sample_04 tests
#[test]
fn test_confirm_ahash_results_sample_04() {
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
@ -382,34 +391,20 @@ mod tests {
18446460933225054208,
18446460933225054208,
];
LIB.with(|lib| {
test_imageset_hash(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::AHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&no_cache_lib,
lib,
);
// Clean_Cache
// super::teardown();
});
}
#[test]
fn test_confirm_dhash_results() {
// Prep_library
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
let no_cache_lib = PIHash::new(None);
// Sample_01 tests
fn test_confirm_dhash_results_sample_01() {
let sample_01_images: [&Path; 3] = [
&Path::new("./test_images/sample_01_large.jpg"),
&Path::new("./test_images/sample_01_medium.jpg"),
@ -420,24 +415,20 @@ mod tests {
3404580580803739582,
3404580580803739582,
];
LIB.with(|lib| {
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&no_cache_lib,
lib,
);
});
}
// Sample_02 tests
#[test]
fn test_confirm_dhash_results_sample_02() {
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
@ -448,24 +439,20 @@ mod tests {
14726771606135242753,
14726771606135242753,
];
LIB.with(|lib| {
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&no_cache_lib,
lib,
);
});
}
// Sample_03 tests
#[test]
fn test_confirm_dhash_results_sample_03() {
let sample_03_images: [&Path; 3] = [
&Path::new("./test_images/sample_03_large.jpg"),
&Path::new("./test_images/sample_03_medium.jpg"),
@ -473,24 +460,20 @@ mod tests {
];
let sample_03_hashes: [u64; 3] =
[144115181601817086, 144115181601817086, 144115181601817086];
LIB.with(|lib| {
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&no_cache_lib,
lib,
);
});
}
// Sample_04 tests
#[test]
fn test_confirm_dhash_results_sample_04() {
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
@ -501,58 +484,37 @@ mod tests {
18374262188442386433,
18374262188442386433,
];
LIB.with(|lib| {
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&lib,
lib,
);
test_imageset_hash(
hash::HashType::DHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&no_cache_lib,
);
// Clean_Cache
// super::teardown();
});
}
#[test]
fn test_confirm_phash_results() {
// Prep_library
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
let no_cache_lib = PIHash::new(None);
// Sample_01 tests
fn test_confirm_phash_results_sample_01() {
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(
test_image_set(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_01_images,
sample_01_hashes,
&no_cache_lib,
);
}
// Sample_02 tests
#[test]
fn test_confirm_phash_results_sample_02() {
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
@ -563,24 +525,17 @@ mod tests {
5332332327550844928,
5332332327550844928,
];
test_imageset_hash(
test_image_set(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_02_images,
sample_02_hashes,
&no_cache_lib,
);
}
// Sample_03 tests
#[test]
fn test_confirm_phash_results_sample_03() {
let sample_03_images: [&Path; 3] = [
&Path::new("./test_images/sample_03_large.jpg"),
&Path::new("./test_images/sample_03_medium.jpg"),
@ -591,24 +546,17 @@ mod tests {
6917529027641081856,
6917529027641081856,
];
test_imageset_hash(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&lib,
);
test_imageset_hash(
test_image_set(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_03_images,
sample_03_hashes,
&no_cache_lib,
);
}
// Sample_04 tests
#[test]
fn test_confirm_phash_results_sample_04() {
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
@ -619,25 +567,13 @@ mod tests {
10997931646002397184,
10997931646002397184,
];
test_imageset_hash(
test_image_set(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&lib,
);
test_imageset_hash(
hash::HashType::PHash,
hash::Precision::Medium,
0u64,
sample_04_images,
sample_04_hashes,
&no_cache_lib,
);
// Clean_Cache
// super::teardown();
}
#[cfg(feature = "bench")]
@ -655,7 +591,6 @@ mod tests {
);
bench.iter(|| {
// Sample_01 Bench
lib.get_perceptual_hash(
&Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium,
@ -671,7 +606,6 @@ mod tests {
let lib = PIHash::new(None);
bench.iter(|| {
// Sample_01 Bench
lib.get_perceptual_hash(
&Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium,

22
src/main.rs

@ -32,6 +32,7 @@ Options:
-a, --ahash Include an ahash calculation.
-d, --dhash Include an dhash calculation.
-p, --phash Include an phash calculation.
-n, --nocache Disable caching behavior.
";
#[derive(Debug, Deserialize)]
@ -42,6 +43,7 @@ struct Args {
flag_phash: bool,
arg_path: String,
arg_comparison: Vec<String>,
flag_nocache: bool,
}
fn main() {
@ -55,8 +57,14 @@ fn main() {
std::process::exit(0);
}
let cache = if args.flag_nocache {
None
} else {
Some(pihash::cache::DEFAULT_CACHE_DIR)
};
// Init the hashing library
let lib = pihash::PIHash::new(Some(pihash::cache::DEFAULT_CACHE_DIR));
let lib = pihash::PIHash::new(cache);
// println!("{:?}", args);
if args.arg_comparison.len() > 0 {
@ -72,10 +80,10 @@ fn main() {
));
}
let mut similar_images: Vec<&str> = Vec::new();
let mut similar_images: Vec<String> = Vec::new();
for comparison_hash in comparison_hashes {
if base_hash.similar(&comparison_hash) {
similar_images.push(&comparison_hash.orig_path);
similar_images.push(String::from(&comparison_hash.orig_path));
}
}
@ -106,11 +114,11 @@ fn flags_get_all_perceptual_hashes(args: &Args) -> bool {
|| (!args.flag_ahash && !args.flag_dhash && !args.flag_phash)
}
fn get_requested_perceptual_hashes<'a>(
fn get_requested_perceptual_hashes(
lib: &pihash::PIHash,
image_path: &'a Path,
image_path: &Path,
args: &Args,
) -> pihash::hash::PerceptualHashes<'a> {
) -> pihash::hash::PerceptualHashes {
let ahash = if args.flag_ahash || flags_get_all_perceptual_hashes(&args) {
lib.get_ahash(&image_path)
} else {
@ -130,7 +138,7 @@ fn get_requested_perceptual_hashes<'a>(
};
pihash::hash::PerceptualHashes {
orig_path: image_path.to_str().unwrap(),
orig_path: String::from(image_path.to_str().unwrap()),
ahash: ahash,
dhash: dhash,
phash: phash,

Loading…
Cancel
Save