image_compare 1.0.0 → 1.0.2
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/CHANGELOG.md +2 -1
- data/README.md +46 -28
- data/lib/image_compare/color_methods.rb +2 -2
- data/lib/image_compare/image.rb +1 -1
- data/lib/image_compare/matcher.rb +14 -12
- data/lib/image_compare/modes/base.rb +2 -2
- data/lib/image_compare/modes/color.rb +6 -6
- data/lib/image_compare/modes/delta.rb +1 -1
- data/lib/image_compare/modes/grayscale.rb +1 -1
- data/lib/image_compare/modes/rgb.rb +1 -1
- data/lib/image_compare/modes.rb +4 -4
- data/lib/image_compare/rectangle.rb +3 -1
- data/lib/image_compare/version.rb +1 -1
- data/lib/image_compare.rb +3 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fddeaa634a928ccfeed4d71797a78d9f8201bc5df036275181ac10addd6a315c
|
4
|
+
data.tar.gz: 43128e9a8fb1c95d246808bdd746ab8023ee984a754e3690b411eb17768399e1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbc5a9c8c6a9b4f34ea24d9259cc0913aa12672dfa10e279134a477a0331b079bd51c1355e1d09b3b0e6a4008ee19c8feda0baa04e3465899b6e001453c15533
|
7
|
+
data.tar.gz: e5cd324880f6f97459eb0b290a3764934f750852d234f775d32ccfbe060cd73152307db6d175f3c120592686e74e9c0509308546f68534c7d741ded33ee99e16
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
3
|
## main
|
4
|
-
- Add Color mode to generate "normal" diff images ([@gsguma][], [@cristianofmc][])
|
4
|
+
- v1.0.0: Add Color mode to generate "normal" diff images ([@gsguma][], [@cristianofmc][])
|
5
|
+
- v1.0.1: Fix all code smells and integration tests ([@gsguma][])
|
5
6
|
|
6
7
|
[@gsguma]: https://github.com/gsguma
|
7
8
|
[@cristianofmc]: https://github.com/cristianofmc
|
data/README.md
CHANGED
@@ -8,10 +8,10 @@ This is an utility library for image regression testing.
|
|
8
8
|
|
9
9
|
## Installation
|
10
10
|
|
11
|
-
Add this line to your application
|
11
|
+
Add this line to your application"s Gemfile:
|
12
12
|
|
13
13
|
```ruby
|
14
|
-
gem
|
14
|
+
gem "image_compare"
|
15
15
|
```
|
16
16
|
|
17
17
|
Or adding to your project:
|
@@ -20,7 +20,7 @@ Or adding to your project:
|
|
20
20
|
# my-cool-gem.gemspec
|
21
21
|
Gem::Specification.new do |spec|
|
22
22
|
# ...
|
23
|
-
spec.add_dependency
|
23
|
+
spec.add_dependency "image_compare"
|
24
24
|
# ...
|
25
25
|
end
|
26
26
|
```
|
@@ -33,8 +33,8 @@ ImageCompare supports different ways (_modes_) of comparing images.
|
|
33
33
|
|
34
34
|
Source images used in examples:
|
35
35
|
|
36
|
-
<img src=
|
37
|
-
<img src=
|
36
|
+
<img alt="a.png" src="spec/fixtures/a.png" />
|
37
|
+
<img alt="b.png" src="spec/fixtures/b.png" />
|
38
38
|
|
39
39
|
### Color
|
40
40
|
|
@@ -42,14 +42,14 @@ Compare pixels, resulting score is a ratio of unequal pixels (with respect to pr
|
|
42
42
|
|
43
43
|
Resulting diff contains version of the first image with different pixels highlighted in red and red bounding box.
|
44
44
|
|
45
|
-
<img src=
|
45
|
+
<img alt="color_diff" src="spec/fixtures/color_diff.png" />
|
46
46
|
|
47
47
|
### Base (RGB) mode
|
48
48
|
|
49
49
|
Compare pixels by values, resulting score is a ratio of unequal pixels.
|
50
50
|
Resulting diff represents per-channel difference.
|
51
51
|
|
52
|
-
<img src=
|
52
|
+
<img alt="rgb_diff.png" src="spec/fixtures/rgb_diff.png" width="480" />
|
53
53
|
|
54
54
|
### Grayscale mode
|
55
55
|
|
@@ -57,14 +57,14 @@ Compare pixels as grayscale (by brightness and alpha), resulting score is a rati
|
|
57
57
|
|
58
58
|
Resulting diff contains grayscale version of the first image with different pixels highlighted in red and red bounding box.
|
59
59
|
|
60
|
-
<img src=
|
60
|
+
<img alt="grayscale_diff.png" src="spec/fixtures/grayscale_diff.png" width="480" />
|
61
61
|
|
62
62
|
### Delta
|
63
63
|
|
64
64
|
Compare pixels using [Delta E](https://en.wikipedia.org/wiki/Color_difference) distance.
|
65
65
|
Resulting diff contains grayscale version of the first image with different pixels highlighted in red (with respect to diff score).
|
66
66
|
|
67
|
-
<img src=
|
67
|
+
<img alt="delta_diff.png" src="spec/fixtures/delta_diff.png" width="480" />
|
68
68
|
|
69
69
|
## Usage
|
70
70
|
|
@@ -91,50 +91,54 @@ cmp.lower_threshold #=> 0.01
|
|
91
91
|
cmp = ImageCompare::Matcher.new mode: :grayscale, tolerance: 0
|
92
92
|
cmp.mode #=> ImageCompare::Modes::Grayscale
|
93
93
|
|
94
|
-
res = cmp.compare(
|
94
|
+
res = cmp.compare("path/image1.png", "path/image2.png")
|
95
95
|
res #=> ImageCompare::Result
|
96
96
|
res.match? #=> true
|
97
97
|
res.score #=> 0.0
|
98
98
|
|
99
99
|
# Return diff image object
|
100
100
|
res.difference_image #=> ImageCompare::Image
|
101
|
-
res.difference_image.save(
|
101
|
+
res.difference_image.save(result)
|
102
102
|
|
103
103
|
# without explicit matcher
|
104
|
-
res = ImageCompare.compare(
|
104
|
+
res = ImageCompare.compare("path/image1.png", "path/image2.png", options)
|
105
|
+
res.match? #=> true
|
106
|
+
res.score #=> 0.0
|
105
107
|
|
106
108
|
# equals to
|
107
|
-
res = ImageCompare::Matcher.new(options).compare(
|
109
|
+
res = ImageCompare::Matcher.new(options).compare("my_images_path/image1.png", "my_images_path/image2.png")
|
110
|
+
res.match? #=> true
|
111
|
+
res.score #=> 0.0
|
108
112
|
```
|
109
113
|
|
110
114
|
## Excluding rectangle
|
111
115
|
|
112
|
-
<img src=
|
113
|
-
<img src=
|
116
|
+
<img alt="a.png" src="spec/fixtures/a.png" />
|
117
|
+
<img alt="a1.png" src="spec/fixtures/a1.png" />
|
114
118
|
|
115
119
|
You can exclude rectangle from comparing by passing `:exclude_rect` to `compare`.
|
116
120
|
E.g., if `path_1` and `path_2` contain images above
|
117
121
|
```ruby
|
118
|
-
ImageCompare.compare(
|
122
|
+
ImageCompare.compare("path/image1.png", "path/image2.png", exclude_rect: [200, 150, 275, 200]).match? # => true
|
119
123
|
|
120
124
|
# or
|
121
125
|
|
122
126
|
cmp = ImageCompare::Matcher.new exclude_rect: [200, 150, 275, 200]
|
123
|
-
res = cmp.compare(
|
127
|
+
res = cmp.compare("path/image1.png", "path/image2.png")
|
124
128
|
res #=> ImageCompare::Result
|
125
129
|
res.match? #=> true
|
126
130
|
res.score #=> 0.0
|
127
131
|
|
128
132
|
# Return diff image object
|
129
133
|
res.difference_image #=> ImageCompare::Image
|
130
|
-
res.difference_image.save(
|
134
|
+
res.difference_image.save("path/diff.png")
|
131
135
|
```
|
132
136
|
`[200, 150, 275, 200]` is array of two vertices of rectangle -- (200, 150) is left-top vertex and (275, 200) is right-bottom.
|
133
137
|
|
134
138
|
### Cucumber + Capybara example
|
135
139
|
`support/env.rb`:
|
136
140
|
```ruby
|
137
|
-
require
|
141
|
+
require "image_compare"
|
138
142
|
```
|
139
143
|
|
140
144
|
`support/capybara_extensions.rb`:
|
@@ -143,15 +147,15 @@ require 'image_compare'
|
|
143
147
|
|
144
148
|
Capybara::Node::Element.class_eval do
|
145
149
|
def rect_area
|
146
|
-
rect_area = self.evaluate_script(
|
150
|
+
rect_area = self.evaluate_script("this.getBoundingClientRect()") # rubocop:disable Style/RedundantSelf
|
147
151
|
|
148
152
|
[
|
149
|
-
rect_area[
|
150
|
-
rect_area[
|
151
|
-
rect_area[
|
152
|
-
rect_area[
|
153
|
+
rect_area["left"].to_f.round,
|
154
|
+
rect_area["top"].to_f.round,
|
155
|
+
rect_area["right"].to_f.round,
|
156
|
+
rect_area["bottom"].to_f.round
|
153
157
|
]
|
154
|
-
rescue StandardError => e
|
158
|
+
rescue StandardError => e # rubocop:disable Style/RescueStandardError
|
155
159
|
raise "Error getting element rect area: #{e.inspect}!"
|
156
160
|
end
|
157
161
|
end
|
@@ -159,11 +163,11 @@ end
|
|
159
163
|
|
160
164
|
`steps/my_step.rb`:
|
161
165
|
```ruby
|
162
|
-
my_element = page.find(
|
166
|
+
my_element = page.find("#my_element").rect_area
|
163
167
|
|
164
168
|
cmp = ImageCompare::Matcher.new exclude_rect: my_element.rect_area
|
165
|
-
res = cmp.compare(
|
166
|
-
res.difference_image.save(
|
169
|
+
res = cmp.compare("path/image1.png", "path/image2.png")
|
170
|
+
res.difference_image.save("path/diff.png")
|
167
171
|
|
168
172
|
expect(res.match?).to eq(true)
|
169
173
|
```
|
@@ -176,6 +180,20 @@ You can set bounds of comparing by passing `:include_rect` to `compare` with arr
|
|
176
180
|
|
177
181
|
Bug reports and pull requests are welcome on GitHub at https://github.com/instantink/image_compare.
|
178
182
|
|
183
|
+
### Running tests and code inspections
|
184
|
+
|
185
|
+
- `rake rubocop`
|
186
|
+
- `rake rubocop:md`
|
187
|
+
- `rake spec`
|
188
|
+
- `ruby examples/performance.rb` Create the gemfile.local file with the content below to run the performance tests:
|
189
|
+
```ruby
|
190
|
+
# frozen_string_literal: true
|
191
|
+
|
192
|
+
source "https://rubygems.org"
|
193
|
+
gem "benchmark-ips", "~> 2.7", ">= 2.7.2"
|
194
|
+
```
|
195
|
+
|
196
|
+
|
179
197
|
## License
|
180
198
|
|
181
199
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/lib/image_compare/image.rb
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
module ImageCompare
|
4
4
|
class Matcher
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
5
|
+
require "image_compare/image"
|
6
|
+
require "image_compare/result"
|
7
|
+
require "image_compare/modes"
|
8
8
|
|
9
9
|
MODES = {
|
10
|
-
rgb:
|
11
|
-
delta:
|
12
|
-
grayscale:
|
13
|
-
color:
|
10
|
+
rgb: "RGB",
|
11
|
+
delta: "Delta",
|
12
|
+
grayscale: "Grayscale",
|
13
|
+
color: "Color"
|
14
14
|
}.freeze
|
15
15
|
|
16
16
|
attr_reader :mode
|
@@ -26,25 +26,27 @@ module ImageCompare
|
|
26
26
|
b = Image.from_file(b) unless b.is_a?(Image)
|
27
27
|
|
28
28
|
unless a.sizes_match?(b)
|
29
|
-
raise
|
30
|
-
|
29
|
+
raise(
|
30
|
+
SizesMismatchError,
|
31
|
+
"Size mismatch: first image size: #{a.width}x#{a.height}, second image size: #{b.width}x#{b.height}"
|
32
|
+
)
|
31
33
|
end
|
32
34
|
|
33
35
|
image_area = Rectangle.new(0, 0, a.width - 1, a.height - 1)
|
34
36
|
|
35
37
|
unless mode.exclude_rect.nil?
|
36
38
|
unless image_area.contains?(mode.exclude_rect)
|
37
|
-
raise ArgumentError,
|
39
|
+
raise ArgumentError, "Bounds must be in image"
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
unless mode.include_rect.nil?
|
42
44
|
unless image_area.contains?(mode.include_rect)
|
43
|
-
raise ArgumentError,
|
45
|
+
raise ArgumentError, "Bounds must be in image"
|
44
46
|
end
|
45
47
|
unless mode.exclude_rect.nil?
|
46
48
|
unless mode.include_rect.contains?(mode.exclude_rect)
|
47
|
-
raise ArgumentError,
|
49
|
+
raise ArgumentError, "Included area must contain excluded"
|
48
50
|
end
|
49
51
|
end
|
50
52
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module ImageCompare
|
4
4
|
module Modes
|
5
5
|
class Base
|
6
|
-
require
|
6
|
+
require "image_compare/rectangle"
|
7
7
|
include ColorMethods
|
8
8
|
|
9
9
|
attr_reader :result, :threshold, :lower_threshold, :bounds, :exclude_rect, :include_rect
|
@@ -22,8 +22,8 @@ module ImageCompare
|
|
22
22
|
@bounds = Rectangle.new(*include_rect.bounds)
|
23
23
|
|
24
24
|
b.compare_each_pixel(a, area: include_rect) do |b_pixel, a_pixel, x, y|
|
25
|
-
next if pixels_equal?(b_pixel, a_pixel)
|
26
25
|
next if !exclude_rect.nil? && exclude_rect.contains_point?(x, y)
|
26
|
+
next if pixels_equal?(b_pixel, a_pixel)
|
27
27
|
update_result(b_pixel, a_pixel, x, y)
|
28
28
|
end
|
29
29
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ImageCompare
|
4
4
|
module Modes
|
5
|
-
require
|
5
|
+
require "image_compare/modes/base"
|
6
6
|
|
7
7
|
class Color < Base
|
8
8
|
include ColorMethods
|
@@ -33,20 +33,20 @@ module ImageCompare
|
|
33
33
|
left: bounds.bounds[0],
|
34
34
|
top: bounds.bounds[1],
|
35
35
|
right: bounds.bounds[2],
|
36
|
-
bot:
|
36
|
+
bot: bounds.bounds[3]
|
37
37
|
}
|
38
38
|
|
39
39
|
exclude_area = {
|
40
40
|
left: exclude_rect.bounds[0],
|
41
41
|
top: exclude_rect.bounds[1],
|
42
42
|
right: exclude_rect.bounds[2],
|
43
|
-
bot:
|
43
|
+
bot: exclude_rect.bounds[3]
|
44
44
|
}
|
45
45
|
|
46
46
|
diff_area[:left] <= exclude_area[:left] &&
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
diff_area[:top] <= exclude_area[:top] &&
|
48
|
+
diff_area[:right] >= exclude_area[:right] &&
|
49
|
+
diff_area[:bot] >= exclude_area[:bot]
|
50
50
|
end
|
51
51
|
|
52
52
|
def pixels_equal?(a, b)
|
data/lib/image_compare/modes.rb
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
module ImageCompare
|
4
4
|
module Modes
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require "image_compare/modes/color"
|
6
|
+
require "image_compare/modes/delta"
|
7
|
+
require "image_compare/modes/grayscale"
|
8
|
+
require "image_compare/modes/rgb"
|
9
9
|
end
|
10
10
|
end
|
@@ -27,7 +27,9 @@ module ImageCompare
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def contains_point?(x, y)
|
30
|
-
x
|
30
|
+
(x >= left && y >= top && x <= right && y <= bot) ||
|
31
|
+
(x <= right && y <= top && x >= left && y >= bot) ||
|
32
|
+
(x.between?(right, left) && y.between?(bot, top))
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
data/lib/image_compare.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require "image_compare/version"
|
4
4
|
|
5
5
|
module ImageCompare
|
6
6
|
class SizesMismatchError < StandardError
|
7
7
|
end
|
8
8
|
|
9
|
-
require
|
10
|
-
require
|
9
|
+
require "image_compare/color_methods"
|
10
|
+
require "image_compare/matcher"
|
11
11
|
|
12
12
|
def self.compare(path_a, path_b, **options)
|
13
13
|
Matcher.new(**options).compare(path_a, path_b)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: image_compare
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- cristianofmc
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-03-
|
12
|
+
date: 2023-03-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: chunky_png
|