dhash-vips 0.2.3.0 → 0.2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ce70f825a89117f682dad1e5ae6400ec3cd430d08d8bb34b36719dff4905894e
4
- data.tar.gz: 17ff221fad7650632cefc04f7421efc79b4f0fe0f2f884d6f1019fc82d360c94
3
+ metadata.gz: 461fbfc5025ae787cb043f8eb7bb1be160ee9d2b0fe58888082d40391afe3338
4
+ data.tar.gz: a56a1ccba11077dec9f266f7ca743b1e678d32439a3eddde134c5ffb10ee7ec8
5
5
  SHA512:
6
- metadata.gz: '019fa1a1b89a5e734332eb1993ea4ccd9dd18b6add3677f065c41cbf0b624986220a094ee5e055cf4f965b56292abe9275ee96fdcbdae53481ea557b0317ad46'
7
- data.tar.gz: 4fa0705056bc27ef272b9a4ca93657bada9646486e0a9532b21d4f53f8d23847188e0b156d66c105054d9a0f2745be4be89b3c9b0244e8e52bc593abd8757a96
6
+ metadata.gz: 7ee718d04a02cfdd9176cbfdb75e57c1645cb44eae6ee3436c9f31f90f27b50b52a9469c24accb2135f2b3359a9f733ad59bb62e6a2046d8849674860021c374
7
+ data.tar.gz: 496b98297106bb8ca3d1bf43e1b67511ea424af5bbdd75afe47d050136f76ae584813fd8e7fb75696499ed0180ae9cc684f30a9a9104c9cc43b140f7f2d74396
data/LICENSE.txt CHANGED
File without changes
data/bin/idhash ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ Signal.trap(:INT){ abort "\n(interrupted by SIGINT)" }
3
+
4
+ unless 2 == ARGV.size
5
+ puts "this command is to compare two images"
6
+ puts "usage: #{__FILE__} <path to image1> <path to image2>"
7
+ exit
8
+ end
9
+
10
+ require_relative "../lib/dhash-vips"
11
+ ha, hb = ARGV.map{ |filename| DHashVips::IDHash.fingerprint filename }
12
+ puts "distance: #{d1 = DHashVips::IDHash.distance ha, hb}"
13
+ size = 2 ** 3
14
+ shift = 2 * size * size
15
+ ai = ha >> shift
16
+ ad = ha - (ai << shift)
17
+ bi = hb >> shift
18
+ bd = hb - (bi << shift)
19
+
20
+ _127 = shift - 1
21
+ _63 = size * size - 1
22
+ # width = 800
23
+ # height = 800
24
+
25
+ d2 = 0
26
+ a, b = [[ad, ai, ARGV[0]], [bd, bi, ARGV[1]]].map do |xd, xi, path|
27
+ puts File.basename path
28
+ hor = Array.new(size){Array.new(size){" "}}
29
+ ver = Array.new(size){Array.new(size){" "}}
30
+ _127.downto(0).each_with_index do |i, ii|
31
+ if i > _63
32
+ y, x = (_127 - i).divmod size
33
+ else
34
+ x, y = (_63 - i).divmod size
35
+ end
36
+ if xi[i] > 0
37
+ target, c = if i > _63
38
+ [ver, %w{ v ^ }[xd[i]]]
39
+ else
40
+ [hor, %w{ > < }[xd[i]]]
41
+ end
42
+ target[y][x] = c
43
+ end
44
+ if ai[i] + bi[i] > 0 && ad[i] != bd[i]
45
+ d2 += 1
46
+ target = if i > _63
47
+ ver
48
+ else
49
+ hor
50
+ end
51
+ target[y][x] = "\e[7m#{target[y][x]}\e[27m"
52
+ end
53
+ end
54
+ hor.zip(ver).each{ |_| puts _.join " " }
55
+ end
56
+ abort "something went wrong" unless d1 * 2 == d2
57
+ puts "OK"
data/dhash-vips.gemspec CHANGED
@@ -1,17 +1,19 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "dhash-vips"
3
- spec.version = "0.2.3.0"
3
+ spec.version = "0.2.5.0"
4
4
  spec.summary = "dHash and IDHash perceptual image hashing/fingerprinting"
5
- # spec.homepage = "https://github.com/nakilon/dhash-vips"
6
5
 
7
- spec.author = "Victor Maslov"
6
+ spec.author = "Victor Maslov aka Nakilon"
8
7
  spec.email = "nakilon@gmail.com"
9
8
  spec.license = "MIT"
9
+ spec.metadata = {"source_code_uri" => "https://github.com/nakilon/dhash-vips"}
10
10
 
11
11
  spec.add_dependency "ruby-vips", "~> 2.0", "!= 2.1.0", "!= 2.1.1"
12
12
 
13
13
  spec.require_path = "lib"
14
- spec.test_files = %w{ test.rb }
15
14
  spec.extensions = %w{ extconf.rb }
16
- spec.files = %w{ extconf.rb Gemfile LICENSE.txt common.rb dhash-vips.gemspec idhash.c lib/dhash-vips-post-install-test.rb lib/dhash-vips.rb }
15
+ spec.files = %w{ LICENSE.txt dhash-vips.gemspec lib/dhash-vips.rb idhash.c lib/dhash-vips-post-install-test.rb } + spec.extensions +
16
+ %w{ bin/idhash }
17
+ spec.executables = %w{ idhash }
18
+ spec.bindir = "bin"
17
19
  end
data/extconf.rb CHANGED
@@ -1,34 +1,23 @@
1
- require "mkmf"
2
-
3
- File.write "Makefile", dummy_makefile(?.).join
4
-
5
1
  unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.8")
6
- if ruby_source_dir = if File.directory? "/ruby"
7
- "-I/ruby" # for Github Actions: docker (currently disabled) and benchmark
8
- elsif ENV["RBENV_ROOT"] && ENV["RBENV_VERSION"] && File.exist?(t = "#{ENV["RBENV_ROOT"]}/sources/#{ENV["RBENV_VERSION"]}/ruby-#{ENV["RBENV_VERSION"]}/bignum.c") # https://github.com/rbenv/rbenv/issues/1199
9
- "-I#{File.dirname t}"
10
- end
11
- append_cppflags ruby_source_dir
12
- append_cppflags "-DRUBY_EXPORT" unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
13
- create_makefile "idhash"
14
- # Why this hack?
15
- # 1. Because I want to use Ruby and ./idhash.bundle for tests, not C.
16
- # 2. Because I don't want to bother users with two gems instead of one.
17
- File.write "Makefile", <<~HEREDOC + File.read("Makefile")
18
- .PHONY: test
19
- test: all
20
- \t$(RUBY) -r./lib/dhash-vips.rb ./lib/dhash-vips-post-install-test.rb
21
- HEREDOC
22
- end
2
+ require "mkmf"
3
+ File.write "Makefile", dummy_makefile(?.).join
4
+ append_cppflags "-DRUBY_EXPORT" unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
5
+ create_makefile "idhash"
6
+ File.write "Makefile", File.read("Makefile") + <<~HEREDOC
7
+ .PHONY: post_install_test
8
+ post_install_test: all
9
+ \t$(RUBY) -r./lib/dhash-vips.rb ./lib/dhash-vips-post-install-test.rb
10
+ HEREDOC
23
11
  end
24
12
 
25
13
  __END__
26
14
 
27
- # this unlike using rake is building to current directory
28
- # that is vital to be able to require the native extention for benchmarking, etc.
15
+ # this unlike using `rake -rbundler/gem_tasks` is building to current directory
16
+ # that is vital to be able to require the native extension for benchmarking, etc.
29
17
  $ ruby extconf.rb && make clean && make
30
18
 
31
- # to test: $ rake clean && rake install
19
+ # to test the installation:
20
+ $ rake -rbundler/gem_tasks clean && rake -rbundler/gem_tasks install
32
21
 
33
22
  $ ruby -e "require 'dhash-vips'; p DHashVips::IDHash.method(:distance3).source_location" # using -r makes bundler mad
34
23
  # [".../dhash-vips.rb", 32] # if LoadError
data/idhash.c CHANGED
@@ -1,29 +1,35 @@
1
- #include <bignum.c>
1
+ #include <ruby.h>
2
2
 
3
- static VALUE idhash_distance(VALUE self, VALUE a, VALUE b){
4
- BDIGIT* tempd;
5
- long i, an = BIGNUM_LEN(a), bn = BIGNUM_LEN(b), templ, acc = 0;
6
- BDIGIT* as = BDIGITS(a);
7
- BDIGIT* bs = BDIGITS(b);
8
- while (0 < an && as[an-1] == 0) an--; // for (i = an; --i;) printf("%u\n", as[i]);
9
- while (0 < bn && bs[bn-1] == 0) bn--; // for (i = bn; --i;) printf("%u\n", bs[i]);
10
- // printf("%lu %lu\n", an, bn);
11
- if (an < bn) {
12
- tempd = as; as = bs; bs = tempd;
13
- templ = an; an = bn; bn = templ;
14
- }
15
- for (i = an; i-- > 4;) {
16
- // printf("%ld : (%u | %u) & (%u ^ %u)\n", i, as[i], (i >= bn ? 0 : bs[i]), as[i-4], bs[i-4]);
17
- acc += __builtin_popcountl((as[i] | (i >= bn ? 0 : bs[i])) & (as[i-4] ^ bs[i-4]));
18
- // printf("%ld : %ld\n", i, acc);
19
- }
20
- RB_GC_GUARD(a);
21
- RB_GC_GUARD(b);
22
- return INT2FIX(acc);
3
+ static VALUE idhash_distance(VALUE self, VALUE a, VALUE b) {
4
+ const size_t max_words = 256 / sizeof(uint64_t);
5
+
6
+ const size_t word_numbits = sizeof(uint64_t) * CHAR_BIT;
7
+ size_t n;
8
+ n = rb_absint_numwords(a, word_numbits, NULL);
9
+ if (n > max_words || n == (size_t)-1)
10
+ rb_raise(rb_eRangeError, "fingerprint #1 exceeds 256 bits");
11
+ n = rb_absint_numwords(b, word_numbits, NULL);
12
+ if (n > max_words || n == (size_t)-1)
13
+ rb_raise(rb_eRangeError, "fingerprint #2 exceeds 256 bits");
14
+
15
+ uint64_t as[max_words], bs[max_words];
16
+ rb_integer_pack(
17
+ a, as, max_words, sizeof(uint64_t), 0,
18
+ INTEGER_PACK_LSWORD_FIRST | INTEGER_PACK_NATIVE_BYTE_ORDER | INTEGER_PACK_2COMP
19
+ );
20
+ rb_integer_pack(
21
+ b, bs, max_words, sizeof(uint64_t), 0,
22
+ INTEGER_PACK_LSWORD_FIRST | INTEGER_PACK_NATIVE_BYTE_ORDER | INTEGER_PACK_2COMP
23
+ );
24
+
25
+ return INT2FIX(
26
+ __builtin_popcountll((as[3] | bs[3]) & (as[1] ^ bs[1])) +
27
+ __builtin_popcountll((as[2] | bs[2]) & (as[0] ^ bs[0]))
28
+ );
23
29
  }
24
30
 
25
31
  void Init_idhash() {
26
- VALUE m = rb_define_module("DHashVips");
27
- VALUE mm = rb_define_module_under(m, "IDHash");
28
- rb_define_module_function(mm, "distance3_c", idhash_distance, 2);
32
+ VALUE m = rb_define_module("DHashVips");
33
+ VALUE mm = rb_define_module_under(m, "IDHash");
34
+ rb_define_module_function(mm, "distance3_c", idhash_distance, 2);
29
35
  }
data/lib/dhash-vips.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  require "vips"
2
- Vips.vector_set false
2
+ ::Vips.vector_set false # TODO: document why?
3
3
 
4
4
  module DHashVips
5
5
 
@@ -15,10 +15,10 @@ module DHashVips
15
15
  end
16
16
 
17
17
  def pixelate input, hash_size
18
- DHashVips.bw( if input.is_a? Vips::Image
18
+ ::DHashVips.bw( if input.is_a? ::Vips::Image
19
19
  input.thumbnail_image(hash_size + 1, height: hash_size, size: :force)
20
20
  else
21
- Vips::Image.thumbnail(input, hash_size + 1, height: hash_size, size: :force)
21
+ ::Vips::Image.thumbnail(input, hash_size + 1, height: hash_size, size: :force)
22
22
  end )
23
23
  end
24
24
 
@@ -35,16 +35,18 @@ module DHashVips
35
35
  ((a ^ b) & (a | b) >> 128).to_s(2).count "1"
36
36
  end
37
37
  begin
38
- require_relative "../idhash.#{Gem::Platform.local.os == "darwin" ? "bundle" : "o"}"
39
- rescue LoadError
38
+ require_relative "../idhash.#{::Gem::Platform.local.os == "darwin" ? "bundle" : "so"}"
39
+ rescue ::LoadError
40
+ warn "C extension for IDHash is not available, using Ruby fallback"
40
41
  class << self
41
42
  alias distance3 distance3_ruby
42
43
  end
43
44
  else
45
+
44
46
  # we can't just do `defined? Bignum` because it's defined but deprecated (some internal CONST_DEPRECATED flag)
45
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
47
+ if ::Gem::Version.new(RUBY_VERSION) < ::Gem::Version.new("2.4")
46
48
  def self.distance3 a, b
47
- if a.is_a?(Bignum) && b.is_a?(Bignum)
49
+ if a.is_a?(::Bignum) && b.is_a?(::Bignum)
48
50
  distance3_c a, b
49
51
  else
50
52
  distance3_ruby a, b
@@ -53,16 +55,19 @@ module DHashVips
53
55
  else
54
56
  # https://github.com/ruby/ruby/commit/de2f7416d2deb4166d78638a41037cb550d64484#diff-16b196bc6bfe8fba63951420f843cfb4R10
55
57
  require "rbconfig/sizeof"
56
- FIXNUM_MAX = (1 << (8 * RbConfig::SIZEOF["long"] - 2)) - 1
58
+ ::FIXNUM_MAX = (1 << (8 * ::RbConfig::SIZEOF["long"] - 2)) - 1
57
59
  def self.distance3 a, b
58
- if a > FIXNUM_MAX && b > FIXNUM_MAX
60
+ if a > ::FIXNUM_MAX && b > ::FIXNUM_MAX
59
61
  distance3_c a, b
60
62
  else
61
63
  distance3_ruby a, b
62
64
  end
63
65
  end
64
66
  end
67
+ # TODO: maybe avoiding Ruby-level if-else would make it faster if we manage to call `#distance3_ruby` from C
68
+
65
69
  end
70
+
66
71
  def self.distance a, b
67
72
  size_a, size_b = [a, b].map do |x|
68
73
  # TODO write a test about possible hash sizes
@@ -98,12 +103,12 @@ module DHashVips
98
103
 
99
104
  def self.fingerprint input, power = 3
100
105
  size = 2 ** power
101
- image = if input.is_a? Vips::Image
106
+ image = if input.is_a? ::Vips::Image
102
107
  input.thumbnail_image(size, height: size, size: :force)
103
108
  else
104
- Vips::Image.thumbnail(input, size, height: size, size: :force)
109
+ ::Vips::Image.thumbnail(input, size, height: size, size: :force)
105
110
  end
106
- array = DHashVips.bw(image).to_enum.map &:flatten
111
+ array = ::DHashVips.bw(image).to_enum.map &:flatten
107
112
  d1, i1, d2, i2 = [array, array.transpose].flat_map do |a|
108
113
  d = a.zip(a.rotate(1)).flat_map{ |r1, r2| r1.zip(r2).map{ |i, j| i - j } }
109
114
  m = median d.map(&:abs).sort
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dhash-vips
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3.0
4
+ version: 0.2.5.0
5
5
  platform: ruby
6
6
  authors:
7
- - Victor Maslov
8
- autorequire:
7
+ - Victor Maslov aka Nakilon
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-23 00:00:00.000000000 Z
11
+ date: 2026-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-vips
@@ -36,27 +36,27 @@ dependencies:
36
36
  - - "!="
37
37
  - !ruby/object:Gem::Version
38
38
  version: 2.1.1
39
- description:
39
+ description:
40
40
  email: nakilon@gmail.com
41
- executables: []
41
+ executables:
42
+ - idhash
42
43
  extensions:
43
44
  - extconf.rb
44
45
  extra_rdoc_files: []
45
46
  files:
46
- - Gemfile
47
47
  - LICENSE.txt
48
- - common.rb
48
+ - bin/idhash
49
49
  - dhash-vips.gemspec
50
50
  - extconf.rb
51
51
  - idhash.c
52
52
  - lib/dhash-vips-post-install-test.rb
53
53
  - lib/dhash-vips.rb
54
- - test.rb
55
- homepage:
54
+ homepage:
56
55
  licenses:
57
56
  - MIT
58
- metadata: {}
59
- post_install_message:
57
+ metadata:
58
+ source_code_uri: https://github.com/nakilon/dhash-vips
59
+ post_install_message:
60
60
  rdoc_options: []
61
61
  require_paths:
62
62
  - lib
@@ -71,9 +71,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
71
  - !ruby/object:Gem::Version
72
72
  version: '0'
73
73
  requirements: []
74
- rubygems_version: 3.3.25
75
- signing_key:
74
+ rubygems_version: 3.2.0
75
+ signing_key:
76
76
  specification_version: 4
77
77
  summary: dHash and IDHash perceptual image hashing/fingerprinting
78
- test_files:
79
- - test.rb
78
+ test_files: []
data/Gemfile DELETED
@@ -1,12 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- gem "rake"
4
- gem "rmagick"
5
- gem "dhash", github: "nakilon/dhash"
6
- gem "phamilie"
7
- gem "get_process_mem"
8
- gem "mll"
9
- gem "minitest"
10
- gem "byebug", "<11.1.0" # for Ruby 2.3
11
-
12
- gemspec
data/common.rb DELETED
@@ -1,11 +0,0 @@
1
- def download_if_needed path
2
- require "open-uri"
3
- require "digest"
4
- FileUtils.mkdir_p File.dirname path
5
- URI("http://gems.nakilon.pro.storage.yandexcloud.net/dhash-vips/#{File.basename path}".tap do |url|
6
- puts "downloading #{path} from #{url}"
7
- end).open do |link|
8
- File.open(path, "wb"){ |file| IO.copy_stream link, file }
9
- end unless File.exist?(path) && Digest::MD5.file(path) == File.basename(path, File.extname(path))
10
- path
11
- end
data/test.rb DELETED
@@ -1,126 +0,0 @@
1
- require "minitest/autorun"
2
-
3
- require_relative "lib/dhash-vips"
4
-
5
- # TODO tests about `fingerprint(4)`
6
-
7
- [
8
- [DHashVips::DHash, :hamming, :calculate, 2, 23, 16, 50, 7, 0x7919395919191919],
9
-
10
- # v0.2.3.0
11
- # [[0, 18, 26, 28, 28, 24, 35, 31, 42, 42, 32, 34, 33, 29, 35, 40],
12
- # [18, 0, 30, 24, 38, 34, 33, 33, 44, 42, 38, 42, 41, 37, 37, 50],
13
- # [26, 30, 0, 16, 34, 38, 29, 35, 42, 40, 36, 38, 31, 31, 31, 36],
14
- # [28, 24, 16, 0, 36, 36, 31, 35, 40, 38, 34, 34, 41, 37, 27, 34],
15
- # [28, 38, 34, 36, 0, 14, 35, 33, 40, 42, 32, 26, 27, 33, 35, 28],
16
- # [24, 34, 38, 36, 14, 0, 43, 39, 38, 40, 24, 28, 25, 31, 29, 28],
17
- # [35, 33, 29, 31, 35, 43, 0, 8, 27, 25, 35, 33, 32, 32, 28, 31],
18
- # [31, 33, 35, 35, 33, 39, 8, 0, 27, 27, 35, 33, 34, 34, 28, 33],
19
- # [42, 44, 42, 40, 40, 38, 27, 27, 0, 2, 34, 32, 31, 33, 31, 28],
20
- # [42, 42, 40, 38, 42, 40, 25, 27, 2, 0, 34, 34, 33, 35, 31, 28],
21
- # [32, 38, 36, 34, 32, 24, 35, 35, 34, 34, 0, 10, 23, 31, 25, 18],
22
- # [34, 42, 38, 34, 26, 28, 33, 33, 32, 34, 10, 0, 23, 29, 25, 16],
23
- # [33, 41, 31, 41, 27, 25, 32, 34, 31, 33, 23, 23, 0, 20, 24, 19],
24
- # [29, 37, 31, 37, 33, 31, 32, 34, 33, 35, 31, 29, 20, 0, 22, 27],
25
- # [35, 37, 31, 27, 35, 29, 28, 28, 31, 31, 25, 25, 24, 22, 0, 23],
26
- # [40, 50, 36, 34, 28, 28, 31, 33, 28, 28, 18, 16, 19, 27, 23, 0]]
27
-
28
- [DHashVips::IDHash, :distance, :fingerprint, 8, 22, 25, 70, 0, 0x1d5cdc0d1d0c1d9f5720a6fff2fe02013f00df9f005e1dc0ff670000ffff0080],
29
-
30
- # v0.2.3.0
31
- # [[0, 19, 34, 38, 57, 47, 50, 49, 45, 42, 55, 45, 60, 49, 51, 53],
32
- # [19, 0, 34, 33, 55, 47, 52, 49, 46, 49, 59, 46, 62, 54, 50, 57],
33
- # [34, 34, 0, 8, 48, 55, 46, 42, 55, 57, 45, 35, 51, 45, 46, 47],
34
- # [38, 33, 8, 0, 52, 61, 43, 38, 49, 50, 50, 37, 50, 39, 43, 51],
35
- # [57, 55, 48, 52, 0, 22, 46, 42, 70, 63, 51, 50, 35, 41, 46, 46],
36
- # [47, 47, 55, 61, 22, 0, 54, 54, 57, 53, 39, 44, 43, 41, 45, 38],
37
- # [50, 52, 46, 43, 46, 54, 0, 8, 35, 38, 51, 45, 50, 42, 43, 43],
38
- # [49, 49, 42, 38, 42, 54, 8, 0, 34, 36, 54, 49, 49, 42, 43, 44],
39
- # [45, 46, 55, 49, 70, 57, 35, 34, 0, 10, 53, 55, 56, 50, 49, 49],
40
- # [42, 49, 57, 50, 63, 53, 38, 36, 10, 0, 50, 52, 55, 48, 46, 45],
41
- # [55, 59, 45, 50, 51, 39, 51, 54, 53, 50, 0, 10, 32, 35, 40, 25],
42
- # [45, 46, 35, 37, 50, 44, 45, 49, 55, 52, 10, 0, 30, 27, 37, 26],
43
- # [60, 62, 51, 50, 35, 43, 50, 49, 56, 55, 32, 30, 0, 22, 26, 28],
44
- # [49, 54, 45, 39, 41, 41, 42, 42, 50, 48, 35, 27, 22, 0, 37, 35],
45
- # [51, 50, 46, 43, 46, 45, 43, 43, 49, 46, 40, 37, 26, 37, 0, 22],
46
- # [53, 57, 47, 51, 46, 38, 43, 44, 49, 45, 25, 26, 28, 35, 22, 0]]
47
-
48
- ].each do |lib, dm, calc, min_similar, max_similar, min_not_similar, max_not_similar, bw_exceptional, hash|
49
-
50
- describe lib do
51
- require "fileutils"
52
- require "digest"
53
- require "mll"
54
-
55
- require_relative "common"
56
-
57
- # these are false positive by idhash
58
- # 1b1d4bde376084011d027bba1c047a4b.jpg
59
- # 6d97739b4a08f965dc9239dd24382e96.jpg
60
- [
61
- [:similar, %w{
62
- 1d468d064d2e26b5b5de9a0241ef2d4b.jpg 92d90b8977f813af803c78107e7f698e.jpg
63
- 309666c7b45ecbf8f13e85a0bd6b0a4c.jpg 3f9f3db06db20d1d9f8188cd753f6ef4.jpg
64
- 679634ff89a31279a39f03e278bc9a01.jpg df0a3b93e9412536ee8a11255f974141.jpg
65
- 54192a3f65bd03163b04849e1577a40b.jpg 6d32f57459e5b79b5deca2a361eb8c6e.jpg
66
- 4b62e0eef58bfbc8d0d2fbf2b9d05483.jpg b8eb0ca91855b657f12fb3d627d45c53.jpg
67
- 21cd9a6986d98976b6b4655e1de7baf4.jpg 9b158c0d4953d47171a22ed84917f812.jpg
68
- 9c2c240ec02356472fb532f404d28dde.jpg fc762fa286489d8afc80adc8cdcb125e.jpg
69
- 7a833d873f8d49f12882e86af1cc6b79.jpg ac033cf01a3941dd1baa876082938bc9.jpg
70
- }, min_similar, max_similar, min_not_similar, max_not_similar], # slightly silimar images
71
- [:bw_exceptional, %w{
72
- 71662d4d4029a3b41d47d5baf681ab9a.jpg ad8a37f872956666c3077a3e9e737984.jpg
73
- }, bw_exceptional, bw_exceptional], # these are the same photo but of different size and colorspace
74
- ].each do |test_name, _images, min, max, min_not, max_not|
75
-
76
- images = _images.map{ |_| download_if_needed "test_images/#{_}" }
77
-
78
- hashes = images.map &lib.method(calc)
79
- table = MLL::table[lib.method(dm), [hashes], [hashes]]
80
-
81
- # STDERR.puts ""
82
- # require "pp"
83
- # PP.pp table, STDERR
84
- # STDERR.puts ""
85
-
86
- it test_name do
87
- similar = []
88
- not_similar = []
89
- hashes.size.times.to_a.repeated_combination(2) do |i, j|
90
- case
91
- when i == j
92
- assert_predicate table[i][j], :zero?
93
- when (j - i).abs == 1 && (i + j - 1) % 4 == 0
94
- # STDERR.puts [table[i][j], min, max].inspect
95
- similar.push table[i][j]
96
- else
97
- # STDERR.puts [table[i][j], min_not_similar, max_not_similar].inspect
98
- not_similar.push table[i][j]
99
- end
100
- end
101
- assert_equal [min, max], similar.minmax
102
- assert_equal [min_not, max_not], not_similar.minmax if min_not
103
- end
104
-
105
- end
106
-
107
- it "accepts Vips::Image" do
108
- # https://github.com/libvips/ruby-vips/issues/349
109
- lib.public_send calc, Vips::Image.new_from_buffer("GIF89a\x01\x00\x01\x00\x80\x01\x00\xFF\xFF\xFF\x00\x00\x00,\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;", "")
110
- end
111
-
112
- it "correct calculation" do
113
- download_if_needed "alpha_only.png"
114
- t = lib.public_send calc, "alpha_only.png"
115
- assert_equal hash, t, ->{ "0x#{hash.to_s 16} != 0x#{t.to_s 16}" }
116
- end
117
-
118
- end
119
-
120
- end
121
-
122
- describe DHashVips::IDHash do
123
- it "does not call distance3_ruby" do
124
- assert_equal :distance3, DHashVips::IDHash.method(:distance3).original_name
125
- end
126
- end