web_image_compare 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.editorconfig +11 -0
- data/.gitignore +27 -0
- data/Gemfile +3 -0
- data/README.md +54 -0
- data/Rakefile +11 -0
- data/lib/chunky_png/operations.rb +44 -0
- data/lib/web_image_compare/version.rb +23 -0
- data/lib/web_image_compare.rb +66 -0
- data/spec/images/example_image.png +0 -0
- data/spec/web_image_compare_spec.rb +18 -0
- data/web_image_compare.gemspec +29 -0
- metadata +139 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 946232f6d4774b842da3cf33c43af3f6a5bc6e03
|
4
|
+
data.tar.gz: 822d61b410e368b681d88fa65a8b14df8db39fb4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e28570f844338d4312feb12d572e25c3908db9b8ffa4b729e0d0d9a53bac72ce4a1d93cc5fbdcfaa5cf082a4183c4d66639c49323ddb19601ef09af937ec68cc
|
7
|
+
data.tar.gz: 7f6553c1f8f48dd2ac0f8f1e6ff6639604af1518a5eb7b5ecc9943086fce76a9189c2e639087afe0aa5148db7ead6fc16adb0bc64a7dabf08f1093e350807431
|
data/.editorconfig
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.idea/
|
6
|
+
coverage
|
7
|
+
InstalledFiles
|
8
|
+
lib/bundler/man
|
9
|
+
pkg
|
10
|
+
rdoc
|
11
|
+
spec/reports
|
12
|
+
test/tmp
|
13
|
+
test/version_tmp
|
14
|
+
tmp
|
15
|
+
.DS_Store
|
16
|
+
|
17
|
+
# Image result from the tests
|
18
|
+
spec/images/*.png_result
|
19
|
+
|
20
|
+
Gemfile.lock
|
21
|
+
report.html
|
22
|
+
bwviziaapi.log
|
23
|
+
|
24
|
+
# YARD artifacts
|
25
|
+
.yardoc
|
26
|
+
_yardoc
|
27
|
+
doc/
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Compare Image tool
|
2
|
+
A tool to compare images from web elements. It is designed to work with Web elements from Capybara (from now on all the references to web elements will be relative to the web elments from capybara) and PNG images.
|
3
|
+
|
4
|
+
|
5
|
+
## What it does?
|
6
|
+
With this tool it is possible crop or hide web elements before perform the image comparison.
|
7
|
+
The crop operation is based on the web element location and in the crop operation already available in the chunky_png gem.
|
8
|
+
The hide feature, is basically, overlap the specific web elment with a black rectangule. It can be used to hide web elements that are always changing, like for example clocks.
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
To use the compare image tool you just have to require the web image compare tool, create an object from WebImageCompare class and then, perform the image comparison calling the 'process_image' method.
|
12
|
+
|
13
|
+
The first argument of the 'process_image' method is to define one of two modes:
|
14
|
+
true - it will record the pattern that will be used in posterior comparisons and it desn't perform any comparison;
|
15
|
+
false - it will perform the image comparison between the pattern image and the new image, both identified when the object was initialized;
|
16
|
+
|
17
|
+
The second argument is an hash than can have two keys (both of them should be symbols):
|
18
|
+
crop - should be the element by which the image will be cropped
|
19
|
+
hide - Should be an array with all the elements to hide
|
20
|
+
|
21
|
+
The result of the image comparison process, wil be the percentual difference between the two images.
|
22
|
+
|
23
|
+
|
24
|
+
###Example:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
require 'WebImageCompare'
|
28
|
+
require 'capybara' # as mentioned the gem works with web elements from capybara
|
29
|
+
|
30
|
+
# Inizialize the browser and navigate to the web page desired
|
31
|
+
# with capybara
|
32
|
+
|
33
|
+
elements = {
|
34
|
+
crop: elem_to_crop'
|
35
|
+
hide: [elem_to_hide_1, elem_to_hide_2]
|
36
|
+
}
|
37
|
+
|
38
|
+
compare_image = WebImageCompare.new(img_pattern_path, img_to_compare_path)
|
39
|
+
compare_image.process_image(record_mode, elements)
|
40
|
+
```
|
41
|
+
|
42
|
+
##Tests
|
43
|
+
|
44
|
+
There are a number of unit tests which are included as part of this project, please run:
|
45
|
+
|
46
|
+
```
|
47
|
+
rspec spec
|
48
|
+
```
|
49
|
+
|
50
|
+
Please note that a number of tests still need to be added so I don't currently have complete coverage, subject to workload these will be slowly added over the next few months.
|
51
|
+
|
52
|
+
|
53
|
+
## Limitations
|
54
|
+
It has the same limitations as the chunky_png, since it is based on it.
|
data/Rakefile
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
module ChunkyPNG
|
2
|
+
# Class Canvas
|
3
|
+
class Canvas
|
4
|
+
# Module operations
|
5
|
+
module Operations
|
6
|
+
include ChunkyPNG::Color
|
7
|
+
|
8
|
+
# Performs the image comparison pixel by pixel
|
9
|
+
#
|
10
|
+
# @param [String] result_img complete path to where is intended save the image
|
11
|
+
# @return [Float] Percentual difference between the two images
|
12
|
+
# @return [Array] Difference image
|
13
|
+
def compare_imgs(pattern_img)
|
14
|
+
fail('height doesn\'t match betwwen the two images') unless pattern_img.height == height
|
15
|
+
fail('width doesn\'t match betwwen the two images') unless pattern_img.width == width
|
16
|
+
|
17
|
+
output = ChunkyPNG::Image.new(pattern_img.width, pattern_img.height, WHITE)
|
18
|
+
|
19
|
+
diff = [0]
|
20
|
+
pattern_img.height.times do |y|
|
21
|
+
pattern_img.row(y).each_with_index do |pixel, x|
|
22
|
+
next if pixel == self[x, y]
|
23
|
+
score = pixel_difference(pixel, self[x, y])
|
24
|
+
output[x, y] = ChunkyPNG.grayscale(MAX - (score * MAX).round)
|
25
|
+
diff << score
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns percentage difference and difference image
|
30
|
+
[diff.inject { |a, e| a + e } / pattern_img.pixels.length * 100, output]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def pixel_difference(pixel_1, pixel_2)
|
37
|
+
Math.sqrt(
|
38
|
+
(r(pixel_1) - r(pixel_2))**2 +
|
39
|
+
(g(pixel_1) - g(pixel_2))**2 +
|
40
|
+
(b(pixel_1) - b(pixel_2))**2
|
41
|
+
) / Math.sqrt(MAX**2 * 3)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module CmpImgTool
|
2
|
+
# BW config api Version
|
3
|
+
module Version
|
4
|
+
# The current gem version
|
5
|
+
VERSION = '0.0.1'
|
6
|
+
# The date version was updated
|
7
|
+
DATE = '2016-02-03'
|
8
|
+
# Debug output that will contain ruby information
|
9
|
+
MSG = 'Version %s %s (running on %s-%s)'
|
10
|
+
|
11
|
+
module_function
|
12
|
+
|
13
|
+
# Outputs the current gem version
|
14
|
+
def version(debug = false)
|
15
|
+
if debug
|
16
|
+
format(MSG, VERSION, DATE, RUBY_ENGINE,
|
17
|
+
RUBY_VERSION)
|
18
|
+
else
|
19
|
+
VERSION
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'chunky_png'
|
2
|
+
require_relative 'chunky_png/operations'
|
3
|
+
|
4
|
+
# Compare image class
|
5
|
+
class WebImageCompare
|
6
|
+
include ChunkyPNG::Color
|
7
|
+
|
8
|
+
# initialize the object with the path for the two images
|
9
|
+
#
|
10
|
+
# @param pattern_file_path [String] Path for the pattern image
|
11
|
+
# @param img_to_compare_path [String] Path for the image that it is to compare
|
12
|
+
def initialize(pattern_file_path, img_to_compare_path)
|
13
|
+
@img_to_compare_path = img_to_compare_path
|
14
|
+
@pattern_img_path = pattern_file_path
|
15
|
+
@pattern_img = ChunkyPNG::Image.from_file(pattern_file_path) if File.file?(pattern_file_path)
|
16
|
+
@img_to_compare = ChunkyPNG::Image.from_file(img_to_compare_path) if File.file?(img_to_compare_path)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Performs the actions to obtain the final image and then
|
20
|
+
# performs the image comparison
|
21
|
+
#
|
22
|
+
# @param record_mode [Boolean] true - saves the pattern image, false - performs the image comparison
|
23
|
+
# @param elements [Hash] Elements to hide or?and crop
|
24
|
+
# @return [Float] Percentual difference between the two images
|
25
|
+
def process_image(record_mode, elements = {})
|
26
|
+
# hide the elements if necessary
|
27
|
+
hide_all_elements(elements[:hide], @img_to_compare) if elements[:hide]
|
28
|
+
|
29
|
+
# crop the element if necessary
|
30
|
+
crop_element(elements[:crop]) if elements[:crop]
|
31
|
+
|
32
|
+
diff_perc = nil
|
33
|
+
if record_mode
|
34
|
+
@img_to_compare.save(@pattern_img_path)
|
35
|
+
return 0
|
36
|
+
else
|
37
|
+
diff_perc, result_img = @img_to_compare.compare_imgs(@pattern_img)
|
38
|
+
@img_to_compare.save("#{@img_to_compare_path}")
|
39
|
+
result_img.save("#{@img_to_compare_path}_result")
|
40
|
+
end
|
41
|
+
diff_perc
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def hide_all_elements(elements, image)
|
47
|
+
elements.each do |element|
|
48
|
+
x1, y1, x2, y2 = coordinates(element)
|
49
|
+
image = image.rect(x1, y1, x1 + x2, y1 + y2, ChunkyPNG::Color::BLACK, ChunkyPNG::Color::BLACK)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def crop_element(element_to_crop)
|
54
|
+
x1, y1, x2, y2 = coordinates(element_to_crop)
|
55
|
+
@img_to_compare.crop!(x1, y1, x2, y2)
|
56
|
+
end
|
57
|
+
|
58
|
+
def coordinates(element)
|
59
|
+
coordinates = []
|
60
|
+
coordinates[0] = element.native.location.x.round
|
61
|
+
coordinates[1] = element.native.location.y.round
|
62
|
+
coordinates[2] = element.native.size.width.round
|
63
|
+
coordinates[3] = element.native.size.height.round
|
64
|
+
coordinates
|
65
|
+
end
|
66
|
+
end
|
Binary file
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'web_image_compare'
|
2
|
+
|
3
|
+
describe WebImageCompare do
|
4
|
+
describe '.new' do
|
5
|
+
it 'is a WebImageCompare instance' do
|
6
|
+
image_path = File.dirname(__FILE__) + '/images/example_image.png'
|
7
|
+
expect(WebImageCompare.new(image_path, image_path)).to be_a WebImageCompare
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '.process_image' do
|
12
|
+
it 'is a perfect match' do
|
13
|
+
image_path = File.dirname(__FILE__) + '/images/example_image.png'
|
14
|
+
compare_image = WebImageCompare.new(image_path, image_path)
|
15
|
+
compare_image.process_image(false, {}).should eq(0.0)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/lib/web_image_compare/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'web_image_compare'
|
5
|
+
s.summary = 'Web'
|
6
|
+
s.description = 'A tool to compare images base in web elements'
|
7
|
+
s.author = 'Rui Nunes'
|
8
|
+
s.email = 'rui@brandwatch.com'
|
9
|
+
s.license = 'MIT'
|
10
|
+
s.homepage = 'https://github.com/Rui-Pedro-Nunes/web-image-compare.git'
|
11
|
+
|
12
|
+
s.date = CmpImgTool::Version::DATE
|
13
|
+
s.version = CmpImgTool::Version::VERSION
|
14
|
+
s.version = "#{s.version}.pre.#{ENV['BUILD_NUMBER']}" if ENV['PRE_RELEASE']
|
15
|
+
|
16
|
+
s.required_ruby_version = '>= 2.0.0'
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
20
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
21
|
+
s.require_paths = ['lib']
|
22
|
+
|
23
|
+
s.add_development_dependency 'rspec', '~> 3.0', '>= 3.0.0'
|
24
|
+
s.add_development_dependency 'rubocop', '~> 0.24', '>= 0.24.1'
|
25
|
+
s.add_development_dependency 'rake', '~> 10.4'
|
26
|
+
s.add_development_dependency 'yard', '~> 0.8'
|
27
|
+
|
28
|
+
s.add_runtime_dependency 'oily_png', '~> 1.2'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: web_image_compare
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rui Nunes
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-02-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 3.0.0
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rubocop
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0.24'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.24.1
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '0.24'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 0.24.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rake
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '10.4'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '10.4'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: yard
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.8'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.8'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: oily_png
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '1.2'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '1.2'
|
95
|
+
description: A tool to compare images base in web elements
|
96
|
+
email: rui@brandwatch.com
|
97
|
+
executables: []
|
98
|
+
extensions: []
|
99
|
+
extra_rdoc_files: []
|
100
|
+
files:
|
101
|
+
- ".editorconfig"
|
102
|
+
- ".gitignore"
|
103
|
+
- Gemfile
|
104
|
+
- README.md
|
105
|
+
- Rakefile
|
106
|
+
- lib/chunky_png/operations.rb
|
107
|
+
- lib/web_image_compare.rb
|
108
|
+
- lib/web_image_compare/version.rb
|
109
|
+
- spec/images/example_image.png
|
110
|
+
- spec/web_image_compare_spec.rb
|
111
|
+
- web_image_compare.gemspec
|
112
|
+
homepage: https://github.com/Rui-Pedro-Nunes/web-image-compare.git
|
113
|
+
licenses:
|
114
|
+
- MIT
|
115
|
+
metadata: {}
|
116
|
+
post_install_message:
|
117
|
+
rdoc_options: []
|
118
|
+
require_paths:
|
119
|
+
- lib
|
120
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 2.0.0
|
125
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - ">="
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '0'
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 2.5.2
|
133
|
+
signing_key:
|
134
|
+
specification_version: 4
|
135
|
+
summary: Web
|
136
|
+
test_files:
|
137
|
+
- spec/images/example_image.png
|
138
|
+
- spec/web_image_compare_spec.rb
|
139
|
+
has_rdoc:
|