phash-0.0.3: src/Data/PHash.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Data.PHash ( hammingDistance
, imagesSimilar
, module Data.PHash.Image
, module Data.PHash.Types ) where
import Control.Applicative ( (<$>)
, (<*>) )
import Foreign.C.Types
import Data.PHash.Image
import Data.PHash.Types
{-|
Calculate the distance between two hashes. This can be used to detect how
similar two images are.
>>> import Data.PHash
>>> hammingDistance (PHash 15243782418149777067) (PHash 17549625427362946731)
2
>>> hammingDistance (PHash 15243782418149777067) (PHash 15243782418149777067)
0
-}
hammingDistance :: PHash -> PHash -> Int
hammingDistance x y = unwrap $ c_ph_hamming_distance (toCPHash x) (toCPHash y)
where unwrap (CInt i) = fromIntegral i
-- |Determine if two images are similar by a user-defined threshold
imagesSimilar :: FilePath
-> FilePath
-> Int -- ^ Threshold for similarity. If the hamming distance exceeds this number, it will return False. 15 seems to be a reasonable default.
-> IO (Maybe Bool)
imagesSimilar p1 p2 threshold = do
h1 <- imageHash p1
h2 <- imageHash p2
return $ checkDistance <$> h1 <*> h2
where checkDistance h1 h2 = (<=threshold) $ hammingDistance h1 h2
foreign import ccall "pHash.h ph_hamming_distance" c_ph_hamming_distance :: CULong -> CULong -> CInt