dhash-vips 0.2.1.0 → 0.2.4.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 +4 -4
- data/LICENSE.txt +0 -0
- data/bin/idhash +57 -0
- data/dhash-vips.gemspec +7 -5
- data/extconf.rb +15 -20
- data/idhash.c +30 -24
- data/lib/dhash-vips.rb +8 -8
- metadata +15 -16
- data/Gemfile +0 -12
- data/common.rb +0 -11
- data/test.rb +0 -225
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6b9bb7ce3d33457aa4a9562c223fc86404304e6a15d92db631462e7f3d3ba1cb
|
4
|
+
data.tar.gz: '09c3df795276527873062983d954ebbdeb07125eccca88551a2fd56f95e13be2'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48e976f177d8fe6dcd010bc0501ec862d2c2bfdad45bfd17e1f6c2f03abd7481e4930683018c7ea879b9c7b339e8676460bea135f943314d25d5dc1b70f76e04
|
7
|
+
data.tar.gz: 23a9ea2f316a226872940e7f0e1dfb3547a01db4ab0c24d981ba4edc68934a02a54be4007aeb7015977c72f7fbf90ead4d092113b45a77c4076feb07ebb421c0
|
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
|
+
spec.version = "0.2.4.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{
|
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
@@ -3,32 +3,27 @@ require "mkmf"
|
|
3
3
|
File.write "Makefile", dummy_makefile(?.).join
|
4
4
|
|
5
5
|
unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.3.8")
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
6
|
+
append_cppflags "-DRUBY_EXPORT" unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.4")
|
7
|
+
create_makefile "idhash"
|
8
|
+
# Why this hack?
|
9
|
+
# 1. Because I want to use Ruby and ./idhash.bundle for tests, not C.
|
10
|
+
# 2. Because I don't want to bother users with two gems instead of one.
|
11
|
+
File.write "Makefile", <<~HEREDOC + File.read("Makefile")
|
12
|
+
.PHONY: test
|
13
|
+
test: all
|
14
|
+
\t$(RUBY) -r./lib/dhash-vips.rb ./lib/dhash-vips-post-install-test.rb
|
15
|
+
HEREDOC
|
23
16
|
end
|
24
17
|
|
25
18
|
__END__
|
26
19
|
|
27
|
-
to test: $ rake clean && rake install
|
28
|
-
|
29
20
|
# this unlike using rake is building to current directory
|
30
|
-
# that is vital to be able to require the native
|
21
|
+
# that is vital to be able to require the native extension for benchmarking, etc.
|
31
22
|
$ ruby extconf.rb && make clean && make
|
23
|
+
|
24
|
+
# to test the installation:
|
25
|
+
$ rake clean && rake install
|
26
|
+
|
32
27
|
$ ruby -e "require 'dhash-vips'; p DHashVips::IDHash.method(:distance3).source_location" # using -r makes bundler mad
|
33
28
|
# [".../dhash-vips.rb", 32] # if LoadError
|
34
29
|
# [".../dhash-vips.rb", 52] # if native (or 42 with Ruby<2.4)
|
data/idhash.c
CHANGED
@@ -1,29 +1,35 @@
|
|
1
|
-
#include <
|
1
|
+
#include <ruby.h>
|
2
2
|
|
3
|
-
static VALUE idhash_distance(VALUE self, VALUE a, VALUE b){
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
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
@@ -3,6 +3,10 @@ Vips.vector_set false
|
|
3
3
|
|
4
4
|
module DHashVips
|
5
5
|
|
6
|
+
def self.bw image
|
7
|
+
(image.has_alpha? ? image.flatten(background: 255) : image).colourspace("b-w")[0]
|
8
|
+
end
|
9
|
+
|
6
10
|
module DHash
|
7
11
|
extend self
|
8
12
|
|
@@ -11,12 +15,11 @@ module DHashVips
|
|
11
15
|
end
|
12
16
|
|
13
17
|
def pixelate input, hash_size
|
14
|
-
|
18
|
+
DHashVips.bw( if input.is_a? Vips::Image
|
15
19
|
input.thumbnail_image(hash_size + 1, height: hash_size, size: :force)
|
16
20
|
else
|
17
21
|
Vips::Image.thumbnail(input, hash_size + 1, height: hash_size, size: :force)
|
18
|
-
end
|
19
|
-
(image.has_alpha? ? image.flatten : image).colourspace("b-w")[0]
|
22
|
+
end )
|
20
23
|
end
|
21
24
|
|
22
25
|
def calculate file, hash_size = 8
|
@@ -35,10 +38,7 @@ module DHashVips
|
|
35
38
|
require_relative "../idhash.#{Gem::Platform.local.os == "darwin" ? "bundle" : "o"}"
|
36
39
|
rescue LoadError
|
37
40
|
class << self
|
38
|
-
|
39
|
-
def distance3 a, b
|
40
|
-
distance3_ruby a, b
|
41
|
-
end
|
41
|
+
alias distance3 distance3_ruby
|
42
42
|
end
|
43
43
|
else
|
44
44
|
# we can't just do `defined? Bignum` because it's defined but deprecated (some internal CONST_DEPRECATED flag)
|
@@ -103,7 +103,7 @@ module DHashVips
|
|
103
103
|
else
|
104
104
|
Vips::Image.thumbnail(input, size, height: size, size: :force)
|
105
105
|
end
|
106
|
-
array = (image
|
106
|
+
array = DHashVips.bw(image).to_enum.map &:flatten
|
107
107
|
d1, i1, d2, i2 = [array, array.transpose].flat_map do |a|
|
108
108
|
d = a.zip(a.rotate(1)).flat_map{ |r1, r2| r1.zip(r2).map{ |i, j| i - j } }
|
109
109
|
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.
|
4
|
+
version: 0.2.4.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:
|
11
|
+
date: 2025-04-12 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
|
-
-
|
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
|
-
|
55
|
-
homepage:
|
54
|
+
homepage:
|
56
55
|
licenses:
|
57
56
|
- MIT
|
58
|
-
metadata:
|
59
|
-
|
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.
|
75
|
-
signing_key:
|
74
|
+
rubygems_version: 3.1.6
|
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
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
|
-
open("http://gems.nakilon.pro.storage.yandexcloud.net/dhash-vips/#{File.basename path}".tap do |url|
|
6
|
-
puts "downloading #{path} from #{url}"
|
7
|
-
end) 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,225 +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, 9, 53, 7],
|
9
|
-
|
10
|
-
# vips-8.9.1-Tue Jan 28 13:05:46 UTC 2020
|
11
|
-
# [[0, 14, 26, 27, 31, 27, 32, 28, 43, 43, 34, 37, 37, 34, 35, 42],
|
12
|
-
# [14, 0, 28, 25, 39, 35, 32, 32, 43, 43, 38, 41, 41, 38, 37, 50],
|
13
|
-
# [26, 28, 0, 13, 35, 41, 28, 30, 41, 41, 36, 33, 35, 32, 27, 36],
|
14
|
-
# [27, 25, 13, 0, 36, 36, 31, 35, 40, 40, 33, 32, 42, 35, 26, 33],
|
15
|
-
# [31, 39, 35, 36, 0, 16, 33, 33, 40, 40, 31, 24, 28, 33, 40, 31],
|
16
|
-
# [27, 35, 41, 36, 16, 0, 41, 41, 38, 38, 23, 26, 24, 29, 34, 27],
|
17
|
-
# [32, 32, 28, 31, 33, 41, 0, 10, 27, 25, 38, 35, 37, 32, 23, 34],
|
18
|
-
# [28, 32, 30, 35, 33, 41, 10, 0, 27, 27, 34, 31, 37, 36, 27, 34],
|
19
|
-
# [43, 43, 41, 40, 40, 38, 27, 27, 0, 2, 35, 34, 30, 31, 28, 27],
|
20
|
-
# [43, 43, 41, 40, 40, 38, 25, 27, 2, 0, 35, 34, 30, 31, 28, 27],
|
21
|
-
# [34, 38, 36, 33, 31, 23, 38, 34, 35, 35, 0, 9, 23, 26, 29, 18],
|
22
|
-
# [37, 41, 33, 32, 24, 26, 35, 31, 34, 34, 9, 0, 22, 25, 30, 19],
|
23
|
-
# [37, 41, 35, 42, 28, 24, 37, 37, 30, 30, 23, 22, 0, 19, 26, 23],
|
24
|
-
# [34, 38, 32, 35, 33, 29, 32, 36, 31, 31, 26, 25, 19, 0, 21, 26],
|
25
|
-
# [35, 37, 27, 26, 40, 34, 23, 27, 28, 28, 29, 30, 26, 21, 0, 23],
|
26
|
-
# [42, 50, 36, 33, 31, 27, 34, 34, 27, 27, 18, 19, 23, 26, 23, 0]]
|
27
|
-
|
28
|
-
# vips-8.11.3-Wed Aug 11 09:29:27 UTC 2021
|
29
|
-
# [[0, 17, 25, 30, 30, 26, 35, 30, 42, 42, 35, 32, 36, 32, 34, 42],
|
30
|
-
# [17, 0, 28, 27, 39, 35, 32, 29, 43, 43, 38, 39, 43, 37, 37, 49],
|
31
|
-
# [25, 28, 0, 13, 35, 41, 28, 29, 41, 41, 38, 35, 33, 31, 27, 37],
|
32
|
-
# [30, 27, 13, 0, 36, 36, 31, 34, 38, 38, 35, 32, 40, 34, 26, 32],
|
33
|
-
# [30, 39, 35, 36, 0, 16, 35, 34, 40, 40, 31, 26, 28, 34, 40, 30],
|
34
|
-
# [26, 35, 41, 36, 16, 0, 41, 44, 38, 38, 23, 28, 26, 30, 34, 24],
|
35
|
-
# [35, 32, 28, 31, 35, 41, 0, 11, 27, 27, 38, 35, 33, 33, 21, 35],
|
36
|
-
# [30, 29, 29, 34, 34, 44, 11, 0, 28, 28, 37, 32, 36, 40, 30, 38],
|
37
|
-
# [42, 43, 41, 38, 40, 38, 27, 28, 0, 0, 33, 34, 30, 32, 28, 30],
|
38
|
-
# [42, 43, 41, 38, 40, 38, 27, 28, 0, 0, 33, 34, 30, 32, 28, 30],
|
39
|
-
# [35, 38, 38, 35, 31, 23, 38, 37, 33, 33, 0, 11, 23, 27, 31, 17],
|
40
|
-
# [32, 39, 35, 32, 26, 28, 35, 32, 34, 34, 11, 0, 24, 26, 30, 20],
|
41
|
-
# [36, 43, 33, 40, 28, 26, 33, 36, 30, 30, 23, 24, 0, 20, 26, 22],
|
42
|
-
# [32, 37, 31, 34, 34, 30, 33, 40, 32, 32, 27, 26, 20, 0, 20, 26],
|
43
|
-
# [34, 37, 27, 26, 40, 34, 21, 30, 28, 28, 31, 30, 26, 20, 0, 24],
|
44
|
-
# [42, 49, 37, 32, 30, 24, 35, 38, 30, 30, 17, 20, 22, 26, 24, 0]]
|
45
|
-
|
46
|
-
# v0.1.2.0
|
47
|
-
# [[0, 18, 25, 27, 28, 25, 33, 31, 39, 40, 33, 35, 32, 28, 36, 47],
|
48
|
-
# [18, 0, 31, 25, 34, 33, 33, 33, 39, 38, 37, 43, 40, 36, 40, 53],
|
49
|
-
# [25, 31, 0, 16, 31, 38, 26, 32, 42, 41, 36, 38, 31, 31, 31, 32],
|
50
|
-
# [27, 25, 16, 0, 35, 36, 26, 32, 38, 37, 34, 34, 41, 37, 27, 34],
|
51
|
-
# [28, 34, 31, 35, 0, 17, 39, 37, 41, 44, 31, 27, 26, 32, 32, 33],
|
52
|
-
# [25, 33, 38, 36, 17, 0, 46, 40, 38, 39, 24, 28, 25, 31, 25, 30],
|
53
|
-
# [33, 33, 26, 26, 39, 46, 0, 10, 26, 25, 34, 32, 31, 35, 33, 30],
|
54
|
-
# [31, 33, 32, 32, 37, 40, 10, 0, 26, 27, 34, 32, 33, 33, 33, 34],
|
55
|
-
# [39, 39, 42, 38, 41, 38, 26, 26, 0, 3, 36, 34, 35, 33, 37, 28],
|
56
|
-
# [40, 38, 41, 37, 44, 39, 25, 27, 3, 0, 35, 35, 36, 36, 36, 27],
|
57
|
-
# [33, 37, 36, 34, 31, 24, 34, 34, 36, 35, 0, 10, 23, 31, 23, 22],
|
58
|
-
# [35, 43, 38, 34, 27, 28, 32, 32, 34, 35, 10, 0, 23, 29, 23, 20],
|
59
|
-
# [32, 40, 31, 41, 26, 25, 31, 33, 35, 36, 23, 23, 0, 20, 24, 21],
|
60
|
-
# [28, 36, 31, 37, 32, 31, 35, 33, 33, 36, 31, 29, 20, 0, 20, 25],
|
61
|
-
# [36, 40, 31, 27, 32, 25, 33, 33, 37, 36, 23, 23, 24, 20, 0, 17],
|
62
|
-
# [47, 53, 32, 34, 33, 30, 30, 34, 28, 27, 22, 20, 21, 25, 17, 0]]
|
63
|
-
|
64
|
-
# v0.2.0.0
|
65
|
-
# [[0, 18, 26, 28, 28, 24, 35, 31, 42, 42, 32, 34, 33, 29, 35, 40],
|
66
|
-
# [18, 0, 30, 24, 38, 34, 33, 33, 44, 42, 38, 42, 41, 37, 37, 50],
|
67
|
-
# [26, 30, 0, 16, 34, 38, 29, 35, 42, 40, 36, 38, 31, 31, 31, 36],
|
68
|
-
# [28, 24, 16, 0, 36, 36, 31, 35, 40, 38, 34, 34, 41, 37, 27, 34],
|
69
|
-
# [28, 38, 34, 36, 0, 14, 35, 33, 40, 42, 32, 26, 27, 33, 35, 28],
|
70
|
-
# [24, 34, 38, 36, 14, 0, 43, 39, 38, 40, 24, 28, 25, 31, 29, 28],
|
71
|
-
# [35, 33, 29, 31, 35, 43, 0, 8, 27, 25, 35, 33, 32, 32, 28, 31],
|
72
|
-
# [31, 33, 35, 35, 33, 39, 8, 0, 27, 27, 35, 33, 34, 34, 28, 33],
|
73
|
-
# [42, 44, 42, 40, 40, 38, 27, 27, 0, 2, 34, 32, 31, 33, 31, 28],
|
74
|
-
# [42, 42, 40, 38, 42, 40, 25, 27, 2, 0, 34, 34, 33, 35, 31, 28],
|
75
|
-
# [32, 38, 36, 34, 32, 24, 35, 35, 34, 34, 0, 10, 23, 31, 25, 18],
|
76
|
-
# [34, 42, 38, 34, 26, 28, 33, 33, 32, 34, 10, 0, 23, 29, 25, 16],
|
77
|
-
# [33, 41, 31, 41, 27, 25, 32, 34, 31, 33, 23, 23, 0, 20, 24, 19],
|
78
|
-
# [29, 37, 31, 37, 33, 31, 32, 34, 33, 35, 31, 29, 20, 0, 22, 27],
|
79
|
-
# [35, 37, 31, 27, 35, 29, 28, 28, 31, 31, 25, 25, 24, 22, 0, 23],
|
80
|
-
# [40, 50, 36, 34, 28, 28, 31, 33, 28, 28, 18, 16, 19, 27, 23, 0]]
|
81
|
-
|
82
|
-
[DHashVips::IDHash, :distance, :fingerprint, 8, 21, 23, 72, 0],
|
83
|
-
|
84
|
-
# vips-8.9.1-Tue Jan 28 13:05:46 UTC 2020
|
85
|
-
# [[0, 16, 32, 35, 57, 45, 51, 50, 48, 47, 54, 48, 60, 50, 47, 56],
|
86
|
-
# [16, 0, 30, 34, 58, 47, 55, 56, 47, 50, 57, 49, 62, 52, 52, 61],
|
87
|
-
# [32, 30, 0, 9, 47, 54, 45, 41, 65, 62, 42, 37, 51, 44, 49, 49],
|
88
|
-
# [35, 34, 9, 0, 54, 64, 42, 40, 57, 56, 48, 39, 50, 40, 41, 51],
|
89
|
-
# [57, 58, 47, 54, 0, 22, 43, 45, 64, 61, 48, 47, 35, 43, 47, 48],
|
90
|
-
# [45, 47, 54, 64, 22, 0, 53, 54, 55, 54, 40, 46, 39, 42, 43, 42],
|
91
|
-
# [51, 55, 45, 42, 43, 53, 0, 6, 33, 35, 52, 43, 46, 45, 44, 47],
|
92
|
-
# [50, 56, 41, 40, 45, 54, 6, 0, 38, 41, 53, 50, 48, 45, 41, 42],
|
93
|
-
# [48, 47, 65, 57, 64, 55, 33, 38, 0, 9, 51, 53, 47, 47, 41, 46],
|
94
|
-
# [47, 50, 62, 56, 61, 54, 35, 41, 9, 0, 51, 57, 50, 49, 44, 43],
|
95
|
-
# [54, 57, 42, 48, 48, 40, 52, 53, 51, 51, 0, 10, 33, 36, 38, 25],
|
96
|
-
# [48, 49, 37, 39, 47, 46, 43, 50, 53, 57, 10, 0, 27, 30, 37, 27],
|
97
|
-
# [60, 62, 51, 50, 35, 39, 46, 48, 47, 50, 33, 27, 0, 20, 23, 28],
|
98
|
-
# [50, 52, 44, 40, 43, 42, 45, 45, 47, 49, 36, 30, 20, 0, 35, 39],
|
99
|
-
# [47, 52, 49, 41, 47, 43, 44, 41, 41, 44, 38, 37, 23, 35, 0, 19],
|
100
|
-
# [56, 61, 49, 51, 48, 42, 47, 42, 46, 43, 25, 27, 28, 39, 19, 0]]
|
101
|
-
|
102
|
-
# vips-8.11.3-Wed Aug 11 09:29:27 UTC 2021
|
103
|
-
# [[0, 17, 30, 35, 55, 46, 51, 54, 48, 46, 57, 48, 59, 52, 49, 54],
|
104
|
-
# [17, 0, 30, 37, 57, 46, 54, 55, 46, 49, 60, 50, 61, 54, 51, 58],
|
105
|
-
# [30, 30, 0, 12, 46, 57, 47, 42, 66, 59, 44, 37, 49, 44, 48, 49],
|
106
|
-
# [35, 37, 12, 0, 54, 67, 44, 41, 58, 53, 48, 41, 56, 42, 46, 48],
|
107
|
-
# [55, 57, 46, 54, 0, 23, 45, 43, 65, 63, 48, 48, 34, 42, 48, 47],
|
108
|
-
# [46, 46, 57, 67, 23, 0, 57, 56, 51, 50, 42, 48, 37, 38, 46, 40],
|
109
|
-
# [51, 54, 47, 44, 45, 57, 0, 6, 33, 34, 49, 43, 49, 41, 45, 47],
|
110
|
-
# [54, 55, 42, 41, 43, 56, 6, 0, 40, 39, 51, 50, 49, 40, 44, 44],
|
111
|
-
# [48, 46, 66, 58, 65, 51, 33, 40, 0, 10, 47, 53, 48, 46, 40, 46],
|
112
|
-
# [46, 49, 59, 53, 63, 50, 34, 39, 10, 0, 50, 57, 50, 49, 40, 43],
|
113
|
-
# [57, 60, 44, 48, 48, 42, 49, 51, 47, 50, 0, 9, 33, 32, 40, 23],
|
114
|
-
# [48, 50, 37, 41, 48, 48, 43, 50, 53, 57, 9, 0, 28, 27, 38, 28],
|
115
|
-
# [59, 61, 49, 56, 34, 37, 49, 49, 48, 50, 33, 28, 0, 21, 24, 27],
|
116
|
-
# [52, 54, 44, 42, 42, 38, 41, 40, 46, 49, 32, 27, 21, 0, 36, 35],
|
117
|
-
# [49, 51, 48, 46, 48, 46, 45, 44, 40, 40, 40, 38, 24, 36, 0, 21],
|
118
|
-
# [54, 58, 49, 48, 47, 40, 47, 44, 46, 43, 23, 28, 27, 35, 21, 0]]
|
119
|
-
|
120
|
-
# v0.1.2.0
|
121
|
-
# [[0, 17, 34, 40, 53, 43, 53, 52, 47, 47, 56, 44, 54, 51, 47, 57],
|
122
|
-
# [17, 0, 35, 33, 56, 45, 56, 52, 48, 49, 58, 49, 64, 57, 53, 58],
|
123
|
-
# [34, 35, 0, 8, 51, 57, 45, 40, 57, 54, 47, 40, 49, 47, 47, 48],
|
124
|
-
# [40, 33, 8, 0, 56, 62, 44, 40, 53, 47, 50, 41, 53, 41, 42, 47],
|
125
|
-
# [53, 56, 51, 56, 0, 21, 41, 48, 72, 65, 46, 47, 36, 43, 43, 43],
|
126
|
-
# [43, 45, 57, 62, 21, 0, 54, 56, 61, 60, 41, 47, 38, 39, 43, 39],
|
127
|
-
# [53, 56, 45, 44, 41, 54, 0, 12, 39, 40, 47, 44, 44, 38, 48, 41],
|
128
|
-
# [52, 52, 40, 40, 48, 56, 12, 0, 35, 36, 51, 50, 47, 39, 41, 43],
|
129
|
-
# [47, 48, 57, 53, 72, 61, 39, 35, 0, 11, 53, 53, 57, 48, 42, 51],
|
130
|
-
# [47, 49, 54, 47, 65, 60, 40, 36, 11, 0, 50, 54, 51, 49, 45, 47],
|
131
|
-
# [56, 58, 47, 50, 46, 41, 47, 51, 53, 50, 0, 13, 32, 36, 38, 23],
|
132
|
-
# [44, 49, 40, 41, 47, 47, 44, 50, 53, 54, 13, 0, 28, 30, 35, 27],
|
133
|
-
# [54, 64, 49, 53, 36, 38, 44, 47, 57, 51, 32, 28, 0, 21, 24, 28],
|
134
|
-
# [51, 57, 47, 41, 43, 39, 38, 39, 48, 49, 36, 30, 21, 0, 31, 35],
|
135
|
-
# [47, 53, 47, 42, 43, 43, 48, 41, 42, 45, 38, 35, 24, 31, 0, 19],
|
136
|
-
# [57, 58, 48, 47, 43, 39, 41, 43, 51, 47, 23, 27, 28, 35, 19, 0]]
|
137
|
-
|
138
|
-
# v0.2.0.0
|
139
|
-
# [[0, 17, 34, 40, 53, 43, 53, 52, 47, 47, 56, 44, 54, 51, 47, 57],
|
140
|
-
# [17, 0, 35, 33, 56, 45, 56, 52, 48, 49, 58, 49, 64, 57, 53, 58],
|
141
|
-
# [34, 35, 0, 8, 51, 57, 45, 40, 57, 54, 47, 40, 49, 47, 47, 48],
|
142
|
-
# [40, 33, 8, 0, 56, 62, 44, 40, 53, 47, 50, 41, 53, 41, 42, 47],
|
143
|
-
# [53, 56, 51, 56, 0, 21, 41, 48, 72, 65, 46, 47, 36, 43, 43, 43],
|
144
|
-
# [43, 45, 57, 62, 21, 0, 54, 56, 61, 60, 41, 47, 38, 39, 43, 39],
|
145
|
-
# [53, 56, 45, 44, 41, 54, 0, 12, 39, 40, 47, 44, 44, 38, 48, 41],
|
146
|
-
# [52, 52, 40, 40, 48, 56, 12, 0, 35, 36, 51, 50, 47, 39, 41, 43],
|
147
|
-
# [47, 48, 57, 53, 72, 61, 39, 35, 0, 11, 53, 53, 57, 48, 42, 51],
|
148
|
-
# [47, 49, 54, 47, 65, 60, 40, 36, 11, 0, 50, 54, 51, 49, 45, 47],
|
149
|
-
# [56, 58, 47, 50, 46, 41, 47, 51, 53, 50, 0, 13, 32, 36, 38, 23],
|
150
|
-
# [44, 49, 40, 41, 47, 47, 44, 50, 53, 54, 13, 0, 28, 30, 35, 27],
|
151
|
-
# [54, 64, 49, 53, 36, 38, 44, 47, 57, 51, 32, 28, 0, 21, 24, 28],
|
152
|
-
# [51, 57, 47, 41, 43, 39, 38, 39, 48, 49, 36, 30, 21, 0, 31, 35],
|
153
|
-
# [47, 53, 47, 42, 43, 43, 48, 41, 42, 45, 38, 35, 24, 31, 0, 19],
|
154
|
-
# [57, 58, 48, 47, 43, 39, 41, 43, 51, 47, 23, 27, 28, 35, 19, 0]]
|
155
|
-
|
156
|
-
].each do |lib, dm, calc, min_similar, max_similar, min_not_similar, max_not_similar, bw_exceptional|
|
157
|
-
|
158
|
-
describe lib do
|
159
|
-
require "fileutils"
|
160
|
-
require "digest"
|
161
|
-
require "mll"
|
162
|
-
|
163
|
-
# these are false positive by idhash
|
164
|
-
# 6d97739b4a08f965dc9239dd24382e96.jpg
|
165
|
-
# 1b1d4bde376084011d027bba1c047a4b.jpg
|
166
|
-
[
|
167
|
-
[ %w{
|
168
|
-
1d468d064d2e26b5b5de9a0241ef2d4b.jpg 92d90b8977f813af803c78107e7f698e.jpg
|
169
|
-
309666c7b45ecbf8f13e85a0bd6b0a4c.jpg 3f9f3db06db20d1d9f8188cd753f6ef4.jpg
|
170
|
-
679634ff89a31279a39f03e278bc9a01.jpg df0a3b93e9412536ee8a11255f974141.jpg
|
171
|
-
54192a3f65bd03163b04849e1577a40b.jpg 6d32f57459e5b79b5deca2a361eb8c6e.jpg
|
172
|
-
4b62e0eef58bfbc8d0d2fbf2b9d05483.jpg b8eb0ca91855b657f12fb3d627d45c53.jpg
|
173
|
-
21cd9a6986d98976b6b4655e1de7baf4.jpg 9b158c0d4953d47171a22ed84917f812.jpg
|
174
|
-
9c2c240ec02356472fb532f404d28dde.jpg fc762fa286489d8afc80adc8cdcb125e.jpg
|
175
|
-
7a833d873f8d49f12882e86af1cc6b79.jpg ac033cf01a3941dd1baa876082938bc9.jpg
|
176
|
-
}, min_similar, max_similar], # slightly silimar images
|
177
|
-
[ %w{
|
178
|
-
71662d4d4029a3b41d47d5baf681ab9a.jpg ad8a37f872956666c3077a3e9e737984.jpg
|
179
|
-
}, bw_exceptional, bw_exceptional], # these are the same photo but of different size and colorspace
|
180
|
-
].each do |_images, min, max|
|
181
|
-
|
182
|
-
require_relative "common"
|
183
|
-
images = _images.map{ |_| download_if_needed "test_images/#{_}" }
|
184
|
-
|
185
|
-
hashes = images.map &lib.method(calc)
|
186
|
-
table = MLL::table[lib.method(dm), [hashes], [hashes]]
|
187
|
-
|
188
|
-
# STDERR.puts ""
|
189
|
-
# require "pp"
|
190
|
-
# PP.pp table, STDERR
|
191
|
-
# STDERR.puts ""
|
192
|
-
|
193
|
-
hashes.size.times.to_a.repeated_combination(2) do |i, j|
|
194
|
-
it "#{_images[i]} #{_images[j]}" do
|
195
|
-
case
|
196
|
-
when i == j
|
197
|
-
assert_predicate table[i][j], :zero?
|
198
|
-
when (j - i).abs == 1 && (i + j - 1) % 4 == 0
|
199
|
-
# STDERR.puts [table[i][j], min, max].inspect
|
200
|
-
assert_includes min..max, table[i][j]
|
201
|
-
else
|
202
|
-
# STDERR.puts [table[i][j], min_not_similar, max_not_similar].inspect
|
203
|
-
assert_includes min_not_similar..max_not_similar, table[i][j]
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
end
|
209
|
-
|
210
|
-
it "accepts Vips::Image" do
|
211
|
-
# https://github.com/libvips/ruby-vips/issues/349
|
212
|
-
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;", "")
|
213
|
-
end
|
214
|
-
|
215
|
-
end
|
216
|
-
|
217
|
-
end
|
218
|
-
|
219
|
-
describe DHashVips::IDHash do
|
220
|
-
it "does not call distance3_ruby" do
|
221
|
-
DHashVips::IDHash.stub :distance3_ruby, ->*{fail} do
|
222
|
-
assert_equal 0, DHashVips::IDHash.distance3((2<<256)-1, (2<<256)-1)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|