Browse Source

Code cleanup and addressing usize vs u32 issues

master
Drew Short 5 years ago
parent
commit
fa97ecc742
  1. 18
      Cargo.toml
  2. 7
      src/cache.rs
  3. 11
      src/hash/ahash.rs
  4. 15
      src/hash/dhash.rs
  5. 16
      src/hash/phash.rs
  6. 185
      src/lib.rs

18
Cargo.toml

@ -1,6 +1,6 @@
[package]
name = "pihash"
version = "0.4.1"
version = "0.5.0"
authors = ["Drew Short <warrick@sothr.com>"]
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/"
@ -20,14 +20,14 @@ default = []
bench = []
[dependencies]
libc = "0.2.36"
rustc-serialize = "0.3.22"
libc = "0.2.62"
rustc-serialize = "0.3.24"
dft = "0.5.5"
image = "0.18.0"
num = "0.1.42"
docopt = "0.8.3"
serde = "1.0"
serde_derive = "1.0"
flate2 = "1.0.1"
image = "0.22.1"
num = "0.2.0"
docopt = "1.1.0"
serde = "1.0.99"
serde_derive = "1.0.99"
flate2 = "1.0.11"
sha1 = "0.6.0"

7
src/cache.rs

@ -167,10 +167,11 @@ impl<'a> Cache<'a> {
// println!("Saving: {}", cache_path_str);
match create_dir_all(cache_dir_str) {
Ok(_) => {
match File::create(Path::new(&cache_path_str)) {
let file_path = Path::new(&cache_path_str);
match File::create(file_path) {
Ok(mut file) => {
// Save the file into the cache
match image.save(&mut file, image::ImageFormat::PNG) {
match image.save(file_path) {
Ok(_) => {}
Err(e) => {
println!("Error: {}", e);
@ -364,7 +365,7 @@ fn test_get_file_hash() {
match hash {
Ok(v) => {
println!("Hash: {}", v);
assert!(v == "4beb6f2d852b75a313863916a1803ebad13a3196");
assert_eq!(v, String::from("4beb6f2d852b75a313863916a1803ebad13a3196"));
}
Err(e) => {
println!("Error: {:?}", e);

11
src/hash/ahash.rs

@ -5,12 +5,15 @@
extern crate image;
use cache::Cache;
use self::image::GenericImage;
use std::path::Path;
use cache::Cache;
use super::{HashType, PerceptualHash, Precision, PreparedImage};
use super::prepare_image;
use self::image::{GenericImage, GenericImageView};
pub struct AHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
}
@ -39,7 +42,7 @@ impl<'a> PerceptualHash for AHash<'a> {
// calculating the average pixel value
let mut total = 0u64;
for (_, _, pixel) in image.pixels() {
total += pixel.data[0] as u64;
total += pixel.0[0] as u64;
}
let mean = total / (height * width) as u64;
// println!("Mean for {} is {}", prepared_image.orig_path, mean);
@ -47,7 +50,7 @@ impl<'a> PerceptualHash for AHash<'a> {
// Calculating a hash based on the mean
let mut hash = 0u64;
for (_, _, pixel) in image.pixels() {
if pixel.data[0] as u64 >= mean {
if pixel.0[0] as u64 >= mean {
hash |= 1;
// println!("Pixel {} is >= {} therefore {:b}", pixel_sum, mean, hash);
} else {

15
src/hash/dhash.rs

@ -4,12 +4,15 @@
// This file may not be copied, modified, or distributed except according to those terms.
extern crate image;
use cache::Cache;
use self::image::GenericImage;
use std::path::Path;
use cache::Cache;
use super::{HashType, PerceptualHash, Precision, PreparedImage};
use super::prepare_image;
use self::image::{GenericImage, GenericImageView};
pub struct DHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
}
@ -35,18 +38,18 @@ impl<'a> PerceptualHash for DHash<'a> {
Some(ref image) => {
let (_, _, first_pixel) = image.pixels().nth(0).unwrap();
let (_, _, last_pixel) = image.pixels().last().unwrap();
let first_pixel_value = first_pixel.data[0] as u64;
let last_pixel_value = last_pixel.data[0] as u64;
let first_pixel_value = first_pixel.0[0] as u64;
let last_pixel_value = last_pixel.0[0] as u64;
// Calculate the dhash
let mut previous_pixel_value = 0u64;
let mut hash = 0u64;
for (x, y, pixel) in image.pixels() {
if x == 0 && y == 0 {
previous_pixel_value = pixel.data[0] as u64;
previous_pixel_value = pixel.0[0] as u64;
continue;
}
let pixel_val = pixel.data[0] as u64;
let pixel_val = pixel.0[0] as u64;
if pixel_val >= previous_pixel_value {
hash |= 1;
} else {

16
src/hash/phash.rs

@ -4,15 +4,18 @@
// This file may not be copied, modified, or distributed except according to those terms.
extern crate image;
use cache::Cache;
use self::image::{GenericImage, DynamicImage};
use std::path::Path;
use cache::Cache;
use super::{HashType, PerceptualHash, Precision, PreparedImage};
use super::dft;
use super::dft::Transform;
use super::image::Pixel;
use super::prepare_image;
use self::image::{DynamicImage, GenericImage, GenericImageView};
pub struct PHash<'a> {
prepared_image: Box<PreparedImage<'a>>,
}
@ -37,8 +40,7 @@ impl<'a> PerceptualHash for PHash<'a> {
match self.prepared_image.image {
Some(ref image) => {
// Get the image data into a vector to perform the DFT on.
let width = image.width() as usize;
let height = image.height() as usize;
let (width, height) = image.dimensions();
// Get 2d data to 2d FFT/DFT
// Either from the cache or calculate it
@ -98,13 +100,13 @@ impl<'a> PerceptualHash for PHash<'a> {
}
}
fn create_data_matrix(width: usize,
height: usize,
fn create_data_matrix(width: u32,
height: u32,
image: &DynamicImage)
-> Vec<Vec<f64>> {
let mut data_matrix: Vec<Vec<f64>> = Vec::new();
// Preparing the results
for x in 0..width {
for x in 0..width as usize {
data_matrix.push(Vec::new());
for y in 0..height {
let pos_x = x as u32;

185
src/lib.rs

@ -6,18 +6,20 @@
// Enable nightly features for extra testing behind the bench feature
#![cfg_attr(feature = "bench", feature(test))]
extern crate image;
extern crate libc;
extern crate rustc_serialize;
#[cfg(feature = "bench")]
extern crate test;
pub mod hash;
pub mod cache;
use std::path::Path;
use std::ffi::CStr;
use std::path::Path;
use cache::Cache;
pub mod hash;
pub mod cache;
#[repr(C)]
pub struct PIHash<'a> {
cache: Option<Cache<'a>>,
@ -174,11 +176,11 @@ pub extern "C" fn ext_get_phash(lib: &PIHash, path_char: *const libc::c_char) ->
pub struct PIHashes {
ahash: libc::uint64_t,
dhash: libc::uint64_t,
phash: libc::uint64_t
phash: libc::uint64_t,
}
#[no_mangle]
pub extern "C" fn ext_get_phashes(lib: &PIHash, path_char: *const libc::c_char) -> * mut PIHashes {
pub extern "C" fn ext_get_phashes(lib: &PIHash, path_char: *const libc::c_char) -> *mut PIHashes {
unsafe {
let path_str = CStr::from_ptr(path_char);
let image_path = match path_str.to_str() {
@ -195,7 +197,7 @@ pub extern "C" fn ext_get_phashes(lib: &PIHash, path_char: *const libc::c_char)
Box::into_raw(Box::new(PIHashes {
ahash: phashes.ahash,
dhash: phashes.dhash,
phash: phashes.phash
phash: phashes.phash,
}))
}
}
@ -222,11 +224,12 @@ fn to_hex_string(bytes: &[u8]) -> String {
//
#[cfg(test)]
mod tests {
use std::fs;
use std::path::Path;
use hash;
use cache;
use hash;
use super::PIHash;
#[cfg(feature = "bench")]
use super::test::Bencher;
@ -302,10 +305,14 @@ mod tests {
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
// Sample_01 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] = [7065306774709811078, 7065306774709811078, 7065306774172940166];
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(hash::HashType::AHash,
hash::Precision::Medium,
1u64,
@ -314,10 +321,14 @@ mod tests {
&lib);
// Sample_02 tests
let sample_02_images: [&Path; 3] = [&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [18446744068986765312, 18446744069246812160, 18446744073541779456];
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [
18446744073441116160,
18446744073441116160,
18446744073441116160];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
3u64,
@ -326,10 +337,14 @@ mod tests {
&lib);
// Sample_03 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] = [108649334536274430, 126663733045756414, 108649334536274430];
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];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
1u64,
@ -338,10 +353,14 @@ mod tests {
&lib);
// Sample_04 tests
let sample_04_images: [&Path; 3] = [&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [18446460933225054208, 18446460933225054208, 18446460933225054208];
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [
18446460933225054208,
18446460933225054208,
18446460933225054208];
test_imageset_hash(hash::HashType::AHash,
hash::Precision::Medium,
0u64,
@ -359,10 +378,14 @@ mod tests {
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
// Sample_01 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] = [18131474507607572478, 18131474507607572478, 18131474507607572478];
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] = [
3404580580803739582,
3404580580803739582,
3404580580803739582];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
0u64,
@ -371,10 +394,14 @@ mod tests {
&lib);
// Sample_02 tests
let sample_02_images: [&Path; 3] = [&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [10088065226894213121, 10088065226894213121, 10088065226894213121];
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [
14726771606135242753,
14726771606135242753,
14726771606135242753];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
0u64,
@ -383,10 +410,14 @@ mod tests {
&lib);
// Sample_03 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] = [144115181601817086, 144115181601817086, 144115181601817086];
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] = [
144115181601817086,
144115181601817086,
144115181601817086];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
0u64,
@ -395,10 +426,14 @@ mod tests {
&lib);
// Sample_04 tests
let sample_04_images: [&Path; 3] = [&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [18374262326015557633, 18374262326015557633, 18374262326283993089];
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [
18374262188442386433,
18374262188442386433,
18374262188442386433];
test_imageset_hash(hash::HashType::DHash,
hash::Precision::Medium,
1u64,
@ -416,10 +451,14 @@ mod tests {
let lib = PIHash::new(Some(cache::DEFAULT_CACHE_DIR));
// Sample_01 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] = [72410537899606272, 72410537899606272, 72410537899606400];
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(hash::HashType::PHash,
hash::Precision::Medium,
1u64,
@ -428,10 +467,14 @@ mod tests {
&lib);
// Sample_02 tests
let sample_02_images: [&Path; 3] = [&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [5620563253458370560, 5620562703702556672, 5620562703702556672];
let sample_02_images: [&Path; 3] = [
&Path::new("./test_images/sample_02_large.jpg"),
&Path::new("./test_images/sample_02_medium.jpg"),
&Path::new("./test_images/sample_02_small.jpg")];
let sample_02_hashes: [u64; 3] = [
5332332327550844928,
5332332327550844928,
5332332327550844928];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
1u64,
@ -440,10 +483,14 @@ mod tests {
&lib);
// Sample_03 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] = [6926536226895822848, 6926536226895822848, 6926536226895822848];
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] = [
6917529027641081856,
6917529027641081856,
6917529027641081856];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
0u64,
@ -452,10 +499,14 @@ mod tests {
&lib);
// Sample_04 tests
let sample_04_images: [&Path; 3] = [&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [11430286023502856200, 10997940459275288576, 11142055647351144448];
let sample_04_images: [&Path; 3] = [
&Path::new("./test_images/sample_04_large.jpg"),
&Path::new("./test_images/sample_04_medium.jpg"),
&Path::new("./test_images/sample_04_small.jpg")];
let sample_04_hashes: [u64; 3] = [
10997931646002397184,
10997931646002397184,
10997931646002397184];
test_imageset_hash(hash::HashType::PHash,
hash::Precision::Medium,
3u64,
@ -480,11 +531,11 @@ mod tests {
&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);
})
// Sample_01 Bench
lib.get_perceptual_hash(&Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium,
&hash::HashType::PHash);
})
}
#[cfg(feature = "bench")]
@ -494,10 +545,10 @@ 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,
&hash::HashType::PHash);
})
// Sample_01 Bench
lib.get_perceptual_hash(&Path::new("./test_images/sample_01_large.jpg"),
&hash::Precision::Medium,
&hash::HashType::PHash);
})
}
}
Loading…
Cancel
Save