ph 0.0.1 → 0.1.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.
Files changed (8) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/Makefile +3 -0
  4. data/README.md +60 -0
  5. data/lib/ph.rb +18 -2
  6. data/ph.gemspec +1 -1
  7. data/spec/ph_spec.rb +22 -20
  8. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 88a7e900bca90ab2c70029559c46848add5f8384a2c60040f012b1ac16691024
4
- data.tar.gz: 4f38f845987a7c33e6d8adb70766e0ea0a0f9758a0efe0e01655370f488f0b96
3
+ metadata.gz: 24b368462e37a0884ab35c35b3fee219c3463e051c4b51a543678412938c46e2
4
+ data.tar.gz: 6e91f21c7e6c1d59259b5eb45e67b4c6e6716346d2c1389ca6a221d80fe216b3
5
5
  SHA512:
6
- metadata.gz: 47c53e0c8a34d0a5c1cbde470000b5de32a246dae9d3f15582ed024b9aaed938fdfcb8b141d5ec845b505765a2ccbab1b46f31b6173886d00c3ff3fcfc1fd7e2
7
- data.tar.gz: 76d82783e82eb7f8d321a79dd21e6a72cafc5014381a6498dcb217f3a29c3c9ab3f1ec9fbf8b4099e31677e1919b4ee1f836e10f520c574a966f06c3762dea86
6
+ metadata.gz: afb8a6f5f61b52a041934f1bb71764b6067665f8f0b505f8772d6a3a11d25565e313d1cb03fb3ff77ab436be379353275fe163241238f0b145c94eb074334e07
7
+ data.tar.gz: e2eeeb235206cc887f3f303702faf11443f8b3e5127fdcd77c21fa6477847bf29ee02ad24a2c64133e74d784f0a5252288ab896a85a4e155a506c14d8e1b7918
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Makefile CHANGED
@@ -9,5 +9,8 @@ build:
9
9
  publish: build
10
10
  gem push *.gem
11
11
 
12
+ console:
13
+ irb -Ilib -rph
14
+
12
15
  test:
13
16
  ruby -Ilib:spec spec/*_spec.rb
data/README.md ADDED
@@ -0,0 +1,60 @@
1
+ # PH
2
+ _Perceptual Hashing_
3
+
4
+ ## Install
5
+
6
+ ```bash
7
+ gem install ph
8
+ ```
9
+
10
+ ## Usage
11
+
12
+ `PH` Generates a perceptual hash from an array of pixels.
13
+ The way you get that pixel data is up to you. Different techniques can shield different values.
14
+ Hashes exist on a similar space but different reads could yield different (subtle) hashes.
15
+
16
+ ### Distance
17
+
18
+ Since hashes exist on a metric space you can measure how far a hash is from another.
19
+ You can use the hamming gem for calculations if needed
20
+
21
+ ```ruby
22
+ Hamming.distance(hash_a, hash_b)
23
+
24
+ # You can also transform hashes based on your storage:
25
+ Hamming.vector_to_hash(hash)
26
+ Hamming.hash_to_vector(vector)
27
+ ```
28
+
29
+ ### Vips
30
+
31
+ ```ruby
32
+ size = 64
33
+ img = Vips::Image.new_from_file(file)
34
+ width, height = img.width, img.height
35
+ w_scale, v_scale = size.fdiv(width), size.fdiv(height)
36
+
37
+ img = img
38
+ .resize(w_scale, vscale: v_scale)
39
+ .colourspace(:grey16)
40
+
41
+ pixels_2d = img.to_a.map(&:flatten)
42
+
43
+ PH.hash(pixels_2d)
44
+ # => "859091ce633aaebb"
45
+ ```
46
+
47
+ ### RMagick
48
+
49
+ ```ruby
50
+ img = Magick::ImageList.new(file)
51
+ size = 64
52
+ img = img
53
+ .scale(size, size)
54
+ .dispatch(0, 0, size, size, "I")
55
+ .each_slice(size)
56
+ .to_a
57
+
58
+ PH.new(img).vector
59
+ # => [1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1]
60
+ ```
data/lib/ph.rb CHANGED
@@ -3,9 +3,25 @@
3
3
  class PH
4
4
  attr_reader :pixels, :size
5
5
 
6
- def initialize(pixels_2d, size: 64)
6
+ NotGreyscaleError = Class.new(StandardError)
7
+ IncorrectDimensionsError = Class.new(StandardError)
8
+
9
+ class << self
10
+ def hash(pixels_2d)
11
+ new(pixels_2d).hash
12
+ end
13
+
14
+ def vector(pixels_2d)
15
+ new(pixels_2d).vector
16
+ end
17
+ end
18
+
19
+ def initialize(pixels_2d)
7
20
  @pixels = pixels_2d
8
- @size = size
21
+ @size = pixels_2d.size
22
+
23
+ raise NotGreyscaleError if pixels_2d.flatten.count != @size**2
24
+ raise IncorrectDimensionsError if !(Math.sqrt(size) % 8).zero?
9
25
  end
10
26
 
11
27
  def hash
data/ph.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = "ph"
5
- s.version = "0.0.1"
5
+ s.version = "0.1.0"
6
6
  s.summary = "Perceptual Hashing"
7
7
  s.authors = ["elcuervo"]
8
8
  s.licenses = %w[MIT]
data/spec/ph_spec.rb CHANGED
@@ -4,30 +4,32 @@ describe PH do
4
4
  let(:file) { "spec/image.jpg" }
5
5
  let(:size) { 64 }
6
6
 
7
- before do
8
- img = Vips::Image.new_from_file(file)
9
- width, height = img.width, img.height
10
- w_scale, v_scale = size.fdiv(width), size.fdiv(height)
7
+ describe "hashing an image" do
8
+ before do
9
+ img = Vips::Image.new_from_file(file)
10
+ width, height = img.width, img.height
11
+ w_scale, v_scale = size.fdiv(width), size.fdiv(height)
11
12
 
12
- # Rescale to 64x64 and greyscale
13
- img = img.resize(w_scale, vscale: v_scale).colourspace(:grey16)
14
- # Ensure a 2D plane
15
- @pixels_2d = img.to_a.map(&:flatten)
16
- end
13
+ # Rescale to 64x64 and greyscale
14
+ img = img.resize(w_scale, vscale: v_scale).colourspace(:grey16)
15
+ # Ensure a 2D plane
16
+ @pixels_2d = img.to_a.map(&:flatten)
17
+ end
17
18
 
18
- subject { PH.new(@pixels_2d) }
19
+ subject { PH.new(@pixels_2d) }
19
20
 
20
- it "#hash" do
21
- assert_equal "859091ce633aaebb", subject.hash
22
- end
21
+ it "#hash" do
22
+ assert_equal "859091ce633aaebb", subject.hash
23
+ end
23
24
 
24
- it "#vector" do
25
- vector = [
26
- 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
27
- 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,
28
- 1, 1
29
- ]
25
+ it "#vector" do
26
+ vector = [
27
+ 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
28
+ 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0,
29
+ 1, 1
30
+ ]
30
31
 
31
- assert_equal vector, subject.vector
32
+ assert_equal vector, subject.vector
33
+ end
32
34
  end
33
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - elcuervo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-02 00:00:00.000000000 Z
11
+ date: 2021-04-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: vips
@@ -31,7 +31,9 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - ".gitignore"
34
35
  - Makefile
36
+ - README.md
35
37
  - lib/ph.rb
36
38
  - ph.gemspec
37
39
  - spec/image.jpg