Skip to main content

phash/
phash.rs

1use img_hash::image;
2use img_hash::{HashAlg, HasherConfig};
3use std::path::Path;
4use thiserror::Error;
5
6#[derive(Debug, Error)]
7pub enum PhashError {
8    #[error(transparent)]
9    Image(#[from] image::ImageError),
10    #[error("hash length unexpected")]
11    BadLength,
12}
13
14/// Perceptual hash as a single `u64` (first 8 bytes of 8×8 gradient hash).
15pub fn phash_u64(path: &Path) -> Result<u64, PhashError> {
16    let img = image::open(path)?;
17    let config = HasherConfig::new()
18        .hash_size(8, 8)
19        .hash_alg(HashAlg::Gradient);
20    let hasher = config.to_hasher();
21    let hash = hasher.hash_image(&img);
22    let bytes = hash.as_bytes();
23    if bytes.len() < 8 {
24        return Err(PhashError::BadLength);
25    }
26    let mut v: u64 = 0;
27    for &b in &bytes[..8] {
28        v = (v << 8) | u64::from(b);
29    }
30    Ok(v)
31}