use average::AverageHasher;
use difference::DifferenceHasher;
use median::MedianHasher;
use perceptual::PerceptualHasher;
use std::path::Path;
pub trait ImageHasher {
fn hash_from_path(&self, path: &Path) -> Result<ImageHash, ImageHashError> {
let img = image::ImageReader::open(path)
.map_err(|e| ImageHashError::IoError {
source: e,
path: path.to_path_buf(),
})?
.decode()?;
self.hash_from_img(&img)
}
fn hash_from_img(&self, img: &image::DynamicImage) -> Result<ImageHash, ImageHashError>;
}
pub fn average_hash(path: &Path) -> Result<ImageHash, ImageHashError> {
let hasher = AverageHasher::default();
hasher.hash_from_path(path)
}
pub fn median_hash(path: &Path) -> Result<ImageHash, ImageHashError> {
let hasher = MedianHasher::default();
hasher.hash_from_path(path)
}
pub fn difference_hash(path: &Path) -> Result<ImageHash, ImageHashError> {
let hasher = DifferenceHasher::default();
hasher.hash_from_path(path)
}
pub fn perceptual_hash(path: &Path) -> Result<ImageHash, ImageHashError> {
let hasher = PerceptualHasher::default();
hasher.hash_from_path(path)
}
pub mod average;
pub mod difference;
pub mod median;
pub mod perceptual;
mod imageops;
mod imghash;
mod math;
pub use crate::imageops::ColorSpace;
pub use crate::imghash::ImageHash;
pub use crate::imghash::ImageHashError;
#[cfg(test)]
mod tests {
use super::*;
const TEST_IMG: &str = "./data/img/test.png";
const TXT_FILE: &str = "./data/misc/test.txt";
#[test]
fn test_average_hash() {
let path = Path::new(TEST_IMG);
let hash = average_hash(path);
assert!(hash.is_ok());
assert_eq!(hash.unwrap().encode().unwrap(), "ffffff0e00000301")
}
#[test]
fn test_average_hash_with_txt_file() {
let path = Path::new(TXT_FILE);
let hash = average_hash(path);
assert!(hash.is_err());
}
#[test]
fn test_median_hash() {
let path = Path::new(TEST_IMG);
let hash = median_hash(path);
assert!(hash.is_ok());
assert_eq!(hash.unwrap().encode().unwrap(), "ffffff1e00000301")
}
#[test]
fn test_median_hash_with_txt_file() {
let path = Path::new(TXT_FILE);
let hash = median_hash(path);
assert!(hash.is_err());
}
#[test]
fn test_difference_hash() {
let path = Path::new(TEST_IMG);
let hash = difference_hash(path);
assert!(hash.is_ok());
assert_eq!(hash.unwrap().encode().unwrap(), "cc99717ed9ea0627")
}
#[test]
fn test_difference_hash_with_txt_file() {
let path = Path::new(TXT_FILE);
let hash = difference_hash(path);
assert!(hash.is_err());
}
#[test]
fn test_perceptual_hash() {
let path = Path::new(TEST_IMG);
let hash = perceptual_hash(path);
assert!(hash.is_ok());
assert_eq!(hash.unwrap().encode().unwrap(), "acdbe86135344e3a")
}
#[test]
fn test_perceptual_hash_with_txt_file() {
let path = Path::new(TXT_FILE);
let hash = perceptual_hash(path);
assert!(hash.is_err());
}
}