require 'phash' module Phash # compute dct robust image hash # # param file string variable for name of file # param hash of type ulong64 (must be 64-bit variable) # return int value - -1 for failure, 1 for success # # int ph_dct_imagehash(const char* file, ulong64 &hash); # attach_function :ph_dct_imagehash, [:string, :pointer], :int, :blocking => true # no info in pHash.h # # int ph_hamming_distance(const ulong64 hash1,const ulong64 hash2); # attach_function :ph_hamming_distance, [:uint64, :uint64], :int, :blocking => true class << self # Get image file hash using ph_dct_imagehash def image_hash(path) hash_p = FFI::MemoryPointer.new :ulong_long if -1 != ph_dct_imagehash(path.to_s, hash_p) hash = hash_p.get_uint64(0) hash_p.free ImageHash.new(hash) end end # Get distance between two image hashes using ph_hamming_distance def image_hamming_distance(hash_a, hash_b) hash_a.is_a?(ImageHash) or raise ArgumentError.new('hash_a is not an ImageHash') hash_b.is_a?(ImageHash) or raise ArgumentError.new('hash_b is not an ImageHash') ph_hamming_distance(hash_a.data, hash_b.data) end # Get similarity from hamming_distance def image_similarity(hash_a, hash_b) 1 - image_hamming_distance(hash_a, hash_b) / 64.0 end end # Class to store image hash and compare to other class ImageHash < HashData private def to_s format('%016x', data) end end # Class to store image file hash and compare to other class Image < FileHash end end