Module: DHashVips::IDHash

Defined in:
lib/dhash-vips.rb

Class Method Summary collapse

Class Method Details

.distance(a, b) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
# File 'lib/dhash-vips.rb', line 66

def self.distance a, b
  size_a, size_b = [a, b].map do |x|
    # TODO write a test about possible hash sizes
    #      they were 32 and 128, 124, 120 for MRI 2.0
    #      but also 31, 30 happens for MRI 2.3
    x.size <= 32 ? 8 : 16
  end
  return distance3 a, b if [8, 8] == [size_a, size_b]
  fail "fingerprints were taken with different `power` param: #{size_a} and #{size_b}" if size_a != size_b
  ((a ^ b) & (a | b) >> 2 * size_a * size_a).to_s(2).count "1"
end

.distance3_ruby(a, b) ⇒ Object



34
35
36
# File 'lib/dhash-vips.rb', line 34

def self.distance3_ruby a, b
  ((a ^ b) & (a | b) >> 128).to_s(2).count "1"
end

.fingerprint(input, power = 3) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/dhash-vips.rb', line 99

def self.fingerprint input, power = 3
  size = 2 ** power
  image = if input.is_a? Vips::Image
    input.thumbnail_image(size, height: size, size: :force)
  else
    Vips::Image.thumbnail(input, size, height: size, size: :force)
  end
  array = DHashVips.bw(image).to_enum.map &:flatten
  d1, i1, d2, i2 = [array, array.transpose].flat_map do |a|
    d = a.zip(a.rotate(1)).flat_map{ |r1, r2| r1.zip(r2).map{ |i, j| i - j } }
    m = median d.map(&:abs).sort
    [
      d.map{ |c| c     <  0 ? 1 : 0 }.join.to_i(2),
      d.map{ |c| c.abs >= m ? 1 : 0 }.join.to_i(2),
    ]
  end
  (((((i1 << size * size) + i2) << size * size) + d1) << size * size) + d2
end