Module: Dcthash

Defined in:
lib/dcthash.rb,
lib/dcthash/version.rb

Overview

DCT Hash Module

Constant Summary collapse

EDGE_SIZE =

Resize each edge of image to this

32
SUBSAMPLE_START =

Grab subsample from this point

1
SUBSAMPLE_END =

Grab subsample to this point

8
VERSION =
"0.1.0"

Class Method Summary collapse

Class Method Details

.calculate(image) ⇒ String

Calculate the hash of an image

Parameters:

  • image (Magick::Image)

    The image to hash

Returns:

  • (String)

    the hash of the image



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/dcthash.rb', line 31

def self.calculate(image)
  image.resize!(EDGE_SIZE, EDGE_SIZE, Magick::PointFilter)
  image = image.quantize(256, Magick::GRAYColorspace, Magick::NoDitherMethod)

  intensity_matrix = image.export_pixels(0, 0, EDGE_SIZE, EDGE_SIZE, "I").each_slice(EDGE_SIZE).to_a

  dct_result = dct_2d(intensity_matrix)
  # @type var sub_matrix: Array[Float]
  sub_matrix = ((dct_result[SUBSAMPLE_START..SUBSAMPLE_END] || [])
  .transpose[SUBSAMPLE_START..SUBSAMPLE_END] || []).flatten

  median = median(sub_matrix)
  result = sub_matrix.map { |px| px < median ? 1 : 0 }
  result.join.to_i(2).to_s(16)
end

.distance(hash1, hash2) ⇒ Integer

Calculate the distance between two hashes

Parameters:

  • hash1 (String)

    The first hash

  • hash2 (String)

    The second hash

Returns:

  • (Integer)

    hamming distance between hashes



15
16
17
# File 'lib/dcthash.rb', line 15

def self.distance(hash1, hash2)
  (hash1.to_i(16) ^ hash2.to_i(16)).to_s(2).count("1")
end

.similar?(hash1, hash2, threshold = 13) ⇒ Boolean

Determine if two hashes are similar

Parameters:

  • hash1 (String)

    The first hash

  • hash2 (String)

    The second hash

  • threshold (Integer) (defaults to: 13)

    (optional) The threshold for similarity

Returns:

  • (Boolean)

    true if hashes are similar



24
25
26
# File 'lib/dcthash.rb', line 24

def self.similar?(hash1, hash2, threshold = 13)
  distance(hash1, hash2) < threshold
end