use image::RgbaImage;
use std::fmt::Debug;
use std::hash::Hash;
pub trait FrameHasher: Send + Sync {
type Hash: Clone + Debug + Send + Sync + Eq + Hash;
fn hash_frame(&self, image: &RgbaImage) -> Self::Hash;
fn distance(&self, a: &Self::Hash, b: &Self::Hash) -> u32;
fn name(&self) -> &'static str;
fn suggested_threshold(&self) -> u32 {
5
}
}
pub trait FrameHasherExt: FrameHasher {
fn hash_frames(&self, images: &[RgbaImage]) -> Vec<Self::Hash> {
images.iter().map(|img| self.hash_frame(img)).collect()
}
fn are_duplicates(&self, a: &RgbaImage, b: &RgbaImage) -> bool {
let hash_a = self.hash_frame(a);
let hash_b = self.hash_frame(b);
self.distance(&hash_a, &hash_b) <= self.suggested_threshold()
}
}
impl<T: FrameHasher> FrameHasherExt for T {}
#[cfg(feature = "parallel")]
mod parallel {
use super::*;
use rayon::prelude::*;
pub trait ParallelFrameHasher: FrameHasher {
fn hash_frames_parallel(&self, images: &[RgbaImage]) -> Vec<Self::Hash>
where
Self::Hash: Send,
{
images.par_iter().map(|img| self.hash_frame(img)).collect()
}
}
impl<T: FrameHasher> ParallelFrameHasher for T {}
}
#[cfg(feature = "parallel")]
pub use parallel::ParallelFrameHasher;