Browse Source

Moved the cache into a struct

develop
Drew Short 9 years ago
parent
commit
b543cb397e
  1. 2
      Cargo.toml
  2. 367
      src/cache.rs
  3. 42
      src/hash.rs
  4. 87
      src/lib.rs

2
Cargo.toml

@ -1,6 +1,6 @@
[package] [package]
name = "pihash" name = "pihash"
version = "0.2.3" version = "0.2.4"
authors = ["Drew Short <warrick@sothr.com>"] authors = ["Drew Short <warrick@sothr.com>"]
description = "A simple library for generating perceptual hashes for images and comparing images based on their perceptual hashes." description = "A simple library for generating perceptual hashes for images and comparing images based on their perceptual hashes."
repository = "https://github.com/warricksothr/Perceptual-Image-Hashing/" repository = "https://github.com/warricksothr/Perceptual-Image-Hashing/"

367
src/cache.rs

@ -19,204 +19,241 @@ use std::io::{Read, Error, Write};
use std::option::Option; use std::option::Option;
use std::result::Result; use std::result::Result;
const CACHE_DIR: &'static str = "./.hash_cache"; pub const CACHE_DIR: &'static str = "./.hash_cache";
const CACHE_FILE_EXT: &'static str = "png"; const CACHED_IMAGE_EXT: &'static str = "png";
const CACHED_MATRIX_EXT: &'static str = "dft";
// Caching version information
const CACHE_VERSION: u32 = 1;
// Creates the required directories /**
pub fn prep_cache() -> Result<(), Error> { * Structure to hold implementation of the cache
create_dir_all(CACHE_DIR) */
pub struct Cache<'a> {
pub cache_dir: &'a str,
} }
pub fn clear_cache() -> Result<(), Error> { impl<'a> Default for Cache<'a> {
remove_dir_all(CACHE_DIR) fn default() -> Cache<'a> { Cache {cache_dir: CACHE_DIR } }
} }
/** impl<'a> Cache<'a> {
* Get the hash of the desired file and return it as a hex string /**
*/ * Create the required directories for the cache
fn get_file_hash(path: &Path) -> Result<String, Error> { */
let mut source = try!(File::open(&path)); pub fn init(&self) -> Result<(), Error> {
let mut buf: Vec<u8> = Vec::new(); create_dir_all(self.cache_dir)
try!(source.read_to_end(&mut buf)); }
let mut sha1 = Sha1::new();
sha1.update(&buf);
// Return the hex result of the hash
Ok(sha1.hexdigest())
}
/** /**
* Put an image buffer in the cache * Clean the cache directory completely
*/ */
pub fn put_image_in_cache(path: &Path, pub fn clean(&self) -> Result<(), Error> {
size: u32, remove_dir_all(self.cache_dir)
image: &ImageBuffer<image::Luma<u8>, Vec<u8>>) }
-> Result<bool, Error> { /**
let hash = get_file_hash(&path); * Get the hash of the desired file and return it as a hex string
match hash { */
Ok(sha1) => { pub fn get_file_hash(&self, path: &Path) -> Result<String, Error> {
let cache_path_str = format!("{}/{}x{}_{}.{}", let mut source = try!(File::open(&path));
CACHE_DIR, let mut buf: Vec<u8> = Vec::new();
size, try!(source.read_to_end(&mut buf));
size, let mut sha1 = Sha1::new();
sha1, sha1.update(&buf);
CACHE_FILE_EXT); // Return the hex result of the hash
let cached_path = Path::new(&cache_path_str); Ok(sha1.hexdigest())
// Save the file into the cache }
match image.save(cached_path) { /**
Ok(_) => {} * Put an image buffer in the cache
Err(e) => { */
println!("Error: {}", e); pub fn put_image_in_cache(&self,
return Err(e); path: &Path,
size: u32,
image: &ImageBuffer<image::Luma<u8>, Vec<u8>>)
-> Result<bool, Error> {
let hash = self.get_file_hash(&path);
match hash {
Ok(sha1) => {
let cache_path_str = format!("{}/image/{}x{}/{}.{}",
CACHE_DIR,
size,
size,
sha1,
CACHED_IMAGE_EXT);
let cache_dir_str = format!("{}/image/{}x{}", self.cache_dir, size, size);
match create_dir_all(cache_dir_str) {
Ok(_) => {
let cached_path = Path::new(&cache_path_str);
// Save the file into the cache
match image.save(cached_path) {
Ok(_) => {}
Err(e) => {
println!("Error: {}", e);
return Err(e);
}
}
},
Err(e) => println!("Error: {}", e),
} }
} }
Err(e) => {
println!("Error: {}", e);
return Err(e);
}
} }
Err(e) => { Ok(true)
println!("Error: {}", e);
return Err(e);
}
} }
Ok(true)
}
/** /**
* Expects a slice of slices that represents lines in the file * Get an image buffer out of the cache
*/ */
pub fn put_matrix_in_cache(path: &Path, pub fn get_image_from_cache(&self,
size: u32, path: &Path,
extension: &str, size: u32)
file_contents: &Vec<Vec<f64>>) -> Option<ImageBuffer<image::Luma<u8>, Vec<u8>>> {
-> Result<bool, Error> { let hash = self.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
let cache_path_str = format!("{}/{}x{}_{}.{}", CACHE_DIR, size, size, sha1, extension); let cache_path_str = format!("{}/image/{}x{}/{}.{}",
let cached_path = Path::new(&cache_path_str); self.cache_dir,
// Save the file into the cache size,
match File::create(&cached_path) { size,
Ok(mut file) => { sha1,
let mut compressor = ZlibEncoder::new(Vec::new(), Compression::Default); CACHED_IMAGE_EXT);
for row in file_contents { let cached_path = Path::new(&cache_path_str);
let mut row_str = row.iter().fold(String::new(), // Try to open, if it does, then we can read the image in
|acc, &item| acc + &format!("{},", item)); match File::open(&cached_path) {
// remove the last comma Ok(_) => {
let desire_len = row_str.len() - 1; let image = image::open(&cached_path).unwrap();
row_str.truncate(desire_len); Some(image.to_luma())
row_str.push_str("\n");
try!(compressor.write(&row_str.into_bytes()));
} }
let compressed_matrix = match compressor.finish() { // Don't really care here, it just means an existing cached
Ok(data) => data, // file doesn't exist, or can't be read.
Err(e) => { Err(_) => None,
println!("Unable to compress matrix data: {}", e);
return Err(e);
}
};
try!(file.write(&compressed_matrix));
try!(file.flush());
}
Err(e) => {
return Err(e);
} }
} }
} Err(e) => {
Err(e) => { println!("Error: {}", e);
println!("Error: {}", e); None
return Err(e); }
} }
} }
Ok(true)
}
/** /**
* Get an image buffer out of the cache * Expects a slice of slices that represents lines in the file
*/ */
pub fn get_image_from_cache(path: &Path, pub fn put_matrix_in_cache(&self,
size: u32) path: &Path,
-> Option<ImageBuffer<image::Luma<u8>, Vec<u8>>> { size: u32,
let hash = get_file_hash(&path); file_contents: &Vec<Vec<f64>>)
match hash { -> Result<bool, Error> {
Ok(sha1) => { let hash = self.get_file_hash(&path);
// Check if the file exists in the cache match hash {
let cache_path_str = format!("{}/{}x{}_{}.{}", Ok(sha1) => {
CACHE_DIR, let cache_path_str = format!("{}/matrix/{}x{}/{}.{}", self.cache_dir, size, size, sha1, CACHED_MATRIX_EXT);
size, let cache_dir_str = format!("{}/matrix/{}x{}", self.cache_dir, size, size);
size, match create_dir_all(cache_dir_str) {
sha1, Ok(_) => {
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
// Try to open, if it does, then we can read the image in match File::create(&cached_path) {
match File::open(&cached_path) { Ok(mut file) => {
Ok(_) => { let mut compressor = ZlibEncoder::new(Vec::new(), Compression::Default);
let image = image::open(&cached_path).unwrap(); for row in file_contents {
Some(image.to_luma()) 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);
row_str.push_str("\n");
try!(compressor.write(&row_str.into_bytes()));
}
let compressed_matrix = match compressor.finish() {
Ok(data) => data,
Err(e) => {
println!("Unable to compress matrix data: {}", e);
return Err(e);
}
};
try!(file.write(&compressed_matrix));
try!(file.flush());
}
Err(e) => {
return Err(e);
}
}
},
Err(e) => println!("Error: {}", e),
} }
// Don't really care here, it just means an existing cached }
// file doesn't exist, or can't be read. Err(e) => {
Err(_) => None, println!("Error: {}", e);
return Err(e);
} }
} }
Err(e) => { Ok(true)
println!("Error: {}", e);
None
}
} }
}
/** /**
* Get a matrix out of the cache * Get a matrix out of the cache
*/ */
pub fn get_matrix_from_cache(path: &Path, size: u32, extension: &str) -> Option<Vec<Vec<f64>>> { pub fn get_matrix_from_cache(&self,
let hash = get_file_hash(&path); path: &Path,
match hash { size: u32)
Ok(sha1) => { -> Option<Vec<Vec<f64>>> {
// Check if the file exists in the cache let hash = self.get_file_hash(&path);
let cache_path_str = format!("{}/{}x{}_{}.{}", CACHE_DIR, size, size, sha1, extension); match hash {
let cached_path = Path::new(&cache_path_str); Ok(sha1) => {
// Try to open, if it does, then we can read the image in // Check if the file exists in the cache
match File::open(&cached_path) { let cache_path_str = format!("{}/matrix/{}x{}/{}.{}", CACHE_DIR, size, size, sha1, CACHED_MATRIX_EXT);
Ok(file) => { let cached_path = Path::new(&cache_path_str);
let mut decoder = ZlibDecoder::new(&file); // Try to open, if it does, then we can read the image in
let mut matrix_data_str = String::new(); match File::open(&cached_path) {
match decoder.read_to_string(&mut matrix_data_str) { Ok(file) => {
Ok(_) => {} let mut decoder = ZlibDecoder::new(&file);
Err(e) => { let mut matrix_data_str = String::new();
println!("Unable to decompress matrix: {}", e); match decoder.read_to_string(&mut matrix_data_str) {
return None; Ok(_) => {}
} Err(e) => {
}; println!("Unable to decompress matrix: {}", e);
// convert the matrix return None;
let matrix: Vec<Vec<f64>> = matrix_data_str.trim() }
.split("\n") };
.map(|line| { // convert the matrix
line.split(",") let matrix: Vec<Vec<f64>> = matrix_data_str.trim()
.map(|f| { .split("\n")
f64::from_str(f).unwrap() .map(|line| {
}) line.split(",")
.collect() .map(|f| {
}) f64::from_str(f).unwrap()
.collect(); })
.collect()
})
.collect();
Some(matrix) Some(matrix)
}
// Don't really care here, it just means an existing cached
// file doesn't exist, or can't be read.
Err(_) => None,
} }
// Don't really care here, it just means an existing cached
// file doesn't exist, or can't be read.
Err(_) => None,
} }
} Err(e) => {
Err(e) => { println!("Error: {}", e);
println!("Error: {}", e); None
None }
} }
} }
} }
#[test] #[test]
fn test_get_file_hash() { fn test_get_file_hash() {
let target = "test_images/sample_01_large.jpg"; let target = "test_images/sample_01_large.jpg";
let target_path = Path::new(target); let target_path = Path::new(target);
let hash = get_file_hash(&target_path); let cache: Cache = Default::default();
let hash = cache.get_file_hash(&target_path);
match hash { match hash {
Ok(v) => { Ok(v) => {
println!("Hash: {}", v); println!("Hash: {}", v);

42
src/hash.rs

@ -12,7 +12,7 @@ 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::Cache;
// Used to get ranges for the precision of rounding floats // Used to get ranges for the precision of rounding floats
// Can round to 1 significant factor of precision // Can round to 1 significant factor of precision
@ -37,6 +37,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>>,
cache: &'a Cache<'a>,
} }
/** /**
@ -56,6 +57,7 @@ pub struct PerceptualHashes<'a> {
* Medium aims for 64 bit precision * Medium aims for 64 bit precision
* High aims for 128 bit precision * High aims for 128 bit precision
*/ */
#[allow(dead_code)]
pub enum Precision { pub enum Precision {
Low, Low,
Medium, Medium,
@ -99,7 +101,8 @@ pub enum HashType {
*/ */
pub fn prepare_image<'a>(path: &'a Path, pub fn prepare_image<'a>(path: &'a Path,
hash_type: &HashType, hash_type: &HashType,
precision: &Precision) precision: &Precision,
cache: &'a Cache<'a>)
-> PreparedImage<'a> { -> 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 {
@ -107,11 +110,12 @@ pub fn prepare_image<'a>(path: &'a Path,
_ => 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 { PreparedImage {
orig_path: &*image_path, orig_path: &*image_path,
image: image, image: image,
cache: &cache
} }
} }
None => { None => {
@ -119,13 +123,14 @@ pub fn prepare_image<'a>(path: &'a Path,
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();
match cache::put_image_in_cache(&path, size, &grey_image) { match cache.put_image_in_cache(&path, size, &grey_image) {
Ok(_) => {} Ok(_) => {}
Err(e) => println!("Unable to store image in cache. {}", e), Err(e) => println!("Unable to store image in cache. {}", e),
}; };
PreparedImage { PreparedImage {
orig_path: &*image_path, orig_path: &*image_path,
image: grey_image, image: grey_image,
cache: &cache,
} }
} }
} }
@ -134,11 +139,11 @@ pub fn prepare_image<'a>(path: &'a Path,
/** /**
* 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) -> 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::new(&path, &precision).get_hash(); let ahash = AHash::new(&path, &precision, &cache).get_hash();
let dhash = DHash::new(&path, &precision).get_hash(); let dhash = DHash::new(&path, &precision, &cache).get_hash();
let phash = PHash::new(&path, &precision).get_hash(); let phash = PHash::new(&path, &precision, &cache).get_hash();
PerceptualHashes { PerceptualHashes {
orig_path: &*image_path, orig_path: &*image_path,
ahash: ahash, ahash: ahash,
@ -149,6 +154,7 @@ pub fn get_perceptual_hashes<'a>(path: &'a Path, precision: &Precision) -> Perce
/** /**
* Calculate the number of bits different between two hashes * Calculate the number of bits different between two hashes
* Add to the PerceptualHashTrait
*/ */
pub fn calculate_hamming_distance(hash1: u64, hash2: u64) -> u64 { pub fn calculate_hamming_distance(hash1: u64, hash2: u64) -> u64 {
// The binary xor of the two hashes should give us a number representing // The binary xor of the two hashes should give us a number representing
@ -175,8 +181,8 @@ pub struct AHash<'a> {
} }
impl<'a> AHash<'a> { impl<'a> AHash<'a> {
pub fn new(path: &'a Path, precision: &Precision) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
AHash { prepared_image: Box::new(prepare_image(&path, &HashType::Ahash, &precision)) } AHash { prepared_image: Box::new(prepare_image(&path, &HashType::Ahash, &precision, &cache)) }
} }
} }
@ -226,8 +232,8 @@ pub struct DHash<'a> {
} }
impl<'a> DHash<'a> { impl<'a> DHash<'a> {
pub fn new(path: &'a Path, precision: &Precision) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
DHash { prepared_image: Box::new(prepare_image(&path, &HashType::Dhash, &precision)) } DHash { prepared_image: Box::new(prepare_image(&path, &HashType::Dhash, &precision, &cache)) }
} }
} }
@ -278,8 +284,8 @@ pub struct PHash<'a> {
} }
impl<'a> PHash<'a> { impl<'a> PHash<'a> {
pub fn new(path: &'a Path, precision: &Precision) -> Self { pub fn new(path: &'a Path, precision: &Precision, cache: &'a Cache) -> Self {
PHash { prepared_image: Box::new(prepare_image(&path, &HashType::Phash, &precision)) } PHash { prepared_image: Box::new(prepare_image(&path, &HashType::Phash, &precision, &cache)) }
} }
} }
@ -301,9 +307,8 @@ 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 cache::get_matrix_from_cache(&Path::new(self.prepared_image.orig_path), match self.prepared_image.cache.get_matrix_from_cache(&Path::new(self.prepared_image.orig_path),
width as u32, width as u32) {
&"dft") {
Some(matrix) => data_matrix = matrix, Some(matrix) => data_matrix = matrix,
None => { None => {
// Preparing the results // Preparing the results
@ -323,9 +328,8 @@ 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 cache::put_matrix_in_cache(&Path::new(self.prepared_image.orig_path), match self.prepared_image.cache.put_matrix_in_cache(&Path::new(self.prepared_image.orig_path),
width as u32, width as u32,
&"dft",
&data_matrix) { &data_matrix) {
Ok(_) => {} Ok(_) => {}
Err(e) => println!("Unable to store matrix in cache. {}", e), Err(e) => println!("Unable to store matrix in cache. {}", e),

87
src/lib.rs

@ -11,6 +11,9 @@ extern crate libc;
use std::path::Path; use std::path::Path;
use hash::PerceptualHash; use hash::PerceptualHash;
use std::ffi::CStr; use std::ffi::CStr;
use cache::Cache;
static LIB_CACHE: Cache<'static> = Cache { cache_dir: cache::CACHE_DIR };
/** /**
* Prepare the library for work. * Prepare the library for work.
@ -19,7 +22,7 @@ use std::ffi::CStr;
*/ */
#[no_mangle] #[no_mangle]
pub extern "C" fn init() { pub extern "C" fn init() {
match cache::prep_cache() { match LIB_CACHE.init() {
Ok(_) => {} Ok(_) => {}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
@ -30,27 +33,27 @@ pub extern "C" fn init() {
*/ */
#[no_mangle] #[no_mangle]
pub extern "C" fn teardown() { pub extern "C" fn teardown() {
match cache::clear_cache() { match LIB_CACHE.clean() {
Ok(_) => {} Ok(_) => {}
Err(e) => println!("Error: {}", e), Err(e) => println!("Error: {}", e),
} }
} }
pub fn get_phashes(path: &Path) -> hash::PerceptualHashes { pub fn get_phashes(path: &Path) -> hash::PerceptualHashes {
hash::get_perceptual_hashes(path, &hash::Precision::Medium) hash::get_perceptual_hashes(path, &hash::Precision::Medium, &LIB_CACHE)
} }
pub fn get_ahash(path: &Path) -> u64 { pub fn get_ahash(path: &Path) -> u64 {
hash::AHash::new(&path, &hash::Precision::Medium).get_hash() hash::AHash::new(&path, &hash::Precision::Medium, &LIB_CACHE).get_hash()
} }
pub fn get_dhash(path: &Path) -> u64 { pub fn get_dhash(path: &Path) -> u64 {
hash::DHash::new(&path, &hash::Precision::Medium).get_hash() hash::DHash::new(&path, &hash::Precision::Medium, &LIB_CACHE).get_hash()
} }
pub fn get_phash(path: &Path) -> u64 { pub fn get_phash(path: &Path) -> u64 {
hash::PHash::new(&path, &hash::Precision::Medium).get_hash() hash::PHash::new(&path, &hash::Precision::Medium, &LIB_CACHE).get_hash()
} }
pub fn get_hamming_distance(hash1: u64, hash2: u64) -> u64 { pub fn get_hamming_distance(hash1: u64, hash2: u64) -> u64 {
@ -220,12 +223,12 @@ mod tests {
// Sample_01 tests // Sample_01 tests
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_01_large.jpg"), test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_01_medium.\ &hash::AHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::AHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
857051991849750, 857051991849750,
857051991849750, 857051991849750,
857051991849750, 857051991849750,
@ -235,12 +238,12 @@ mod tests {
// Sample_02 tests // Sample_02 tests
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_02_large.jpg"), test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_02_medium.\ &hash::AHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::AHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
18446744073441116160, 18446744073441116160,
18446744073441116160, 18446744073441116160,
18446744073441116160, 18446744073441116160,
@ -249,12 +252,12 @@ mod tests {
0u64); 0u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_03_large.jpg"), test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_03_medium.\ &hash::AHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::AHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
135670932300497406, 135670932300497406,
135670932300497406, 135670932300497406,
135670932300497406, 135670932300497406,
@ -264,12 +267,12 @@ mod tests {
// Sample_04 tests // Sample_04 tests
test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_04_large.jpg"), test_imageset_hash(&hash::AHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_04_medium.\ &hash::AHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::AHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::AHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
18446460933225054208, 18446460933225054208,
18446460933090836480, 18446460933090836480,
18446460933090836480, 18446460933090836480,
@ -288,12 +291,12 @@ mod tests {
// Sample_01 tests // Sample_01 tests
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_01_large.jpg"), test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_01_medium.\ &hash::DHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::DHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
7937395827556495926, 7937395827556495926,
7937395827556495926, 7937395827556495926,
7939647627370181174, 7939647627370181174,
@ -303,12 +306,12 @@ mod tests {
// Sample_02 tests // Sample_02 tests
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_02_large.jpg"), test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_02_medium.\ &hash::DHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::DHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
11009829669713008949, 11009829669713008949,
11009829670249879861, 11009829670249879861,
11009829669713008949, 11009829669713008949,
@ -317,12 +320,12 @@ mod tests {
1u64); 1u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_03_large.jpg"), test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_03_medium.\ &hash::DHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::DHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
225528496439353286, 225528496439353286,
225528496439353286, 225528496439353286,
226654396346195908, 226654396346195908,
@ -332,12 +335,12 @@ mod tests {
// Sample_04 tests // Sample_04 tests
test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_04_large.jpg"), test_imageset_hash(&hash::DHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_04_medium.\ &hash::DHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::DHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::DHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
14620651386429567209, 14620651386429567209,
14620651386429567209, 14620651386429567209,
14620651386429567209, 14620651386429567209,
@ -356,12 +359,12 @@ mod tests {
// Sample_01 tests // Sample_01 tests
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_01_large.jpg"), test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_01_medium.\ &hash::PHash::new(path::Path::new("./test_images/sample_01_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_01_small.jpg"), &hash::PHash::new(path::Path::new("./test_images/sample_01_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
72357778504597504, 72357778504597504,
72357778504597504, 72357778504597504,
72357778504597504, 72357778504597504,
@ -371,12 +374,12 @@ mod tests {
// Sample_02 tests // Sample_02 tests
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_02_large.jpg"), test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_02_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_02_medium.\ &hash::PHash::new(path::Path::new("./test_images/sample_02_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_02_small.jpg"), &hash::PHash::new(path::Path::new("./test_images/sample_02_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
5332332327550844928, 5332332327550844928,
5332332327550844928, 5332332327550844928,
5332332327550844928, 5332332327550844928,
@ -385,12 +388,12 @@ mod tests {
0u64); 0u64);
// Sample_03 tests // Sample_03 tests
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_03_large.jpg"), test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_03_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_03_medium.\ &hash::PHash::new(path::Path::new("./test_images/sample_03_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_03_small.jpg"), &hash::PHash::new(path::Path::new("./test_images/sample_03_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
6917529027641081856, 6917529027641081856,
6917529027641081856, 6917529027641081856,
6917529027641081856, 6917529027641081856,
@ -400,12 +403,12 @@ mod tests {
// Sample_04 tests // Sample_04 tests
test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_04_large.jpg"), test_imageset_hash(&hash::PHash::new(path::Path::new("./test_images/sample_04_large.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_04_medium.\ &hash::PHash::new(path::Path::new("./test_images/sample_04_medium.\
jpg"), jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
&hash::PHash::new(path::Path::new("./test_images/sample_04_small.jpg"), &hash::PHash::new(path::Path::new("./test_images/sample_04_small.jpg"),
&hash::Precision::Medium), &hash::Precision::Medium, &super::LIB_CACHE),
10997931646002397184, 10997931646002397184,
10997931646002397184, 10997931646002397184,
11142046834078253056, 11142046834078253056,

|||||||
100:0
Loading…
Cancel
Save