screenpress 0.2.1 → 0.3.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.
- data/lib/screenpress.rb +5 -1
- data/lib/screenpress/compare/bits.rb +105 -0
- data/lib/screenpress/compare/phashion.rb +23 -0
- data/lib/screenpress/config.rb +15 -1
- data/lib/screenpress/saver.rb +44 -2
- data/lib/screenpress/version.rb +1 -1
- data/screenpress.gemspec +2 -0
- metadata +20 -3
- data/lib/screenpress/compare.rb +0 -120
data/lib/screenpress.rb
CHANGED
@@ -3,10 +3,14 @@ require "capybara"
|
|
3
3
|
|
4
4
|
module Screenpress
|
5
5
|
autoload :Config, 'screenpress/config'
|
6
|
-
autoload :Compare, 'screenpress/compare'
|
7
6
|
autoload :DSL, 'screenpress/dsl'
|
8
7
|
autoload :Saver, 'screenpress/saver'
|
9
8
|
|
9
|
+
module Compare
|
10
|
+
autoload :Bits, 'screenpress/compare/bits'
|
11
|
+
autoload :Phashion, 'screenpress/compare/phashion'
|
12
|
+
end
|
13
|
+
|
10
14
|
class << self
|
11
15
|
def config
|
12
16
|
@config ||= Screenpress::Config.new
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# based on: https://github.com/intridea/green_onion/blob/master/lib/green_onion/compare.rb
|
2
|
+
|
3
|
+
require "oily_png"
|
4
|
+
|
5
|
+
module Screenpress
|
6
|
+
module Compare
|
7
|
+
class Bits
|
8
|
+
include ChunkyPNG::Color
|
9
|
+
|
10
|
+
attr_reader :orig_image, :fresh_image
|
11
|
+
def initialize(orig_path, fresh_path)
|
12
|
+
@orig_image = ChunkyPNG::Image.from_file(orig_path)
|
13
|
+
@fresh_image = ChunkyPNG::Image.from_file(fresh_path)
|
14
|
+
@diff_index = []
|
15
|
+
end
|
16
|
+
|
17
|
+
def difference
|
18
|
+
diff_iterator
|
19
|
+
percentage_diff
|
20
|
+
end
|
21
|
+
|
22
|
+
def threshold
|
23
|
+
Screenpress.config.threshold || 0.1
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# Pulled from Jeff Kreeftmeijer's post here: http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/
|
29
|
+
# Run through all of the pixels on both org image, and fresh image. Change the pixel color accordingly.
|
30
|
+
def update_diff_index(x, y, pixel)
|
31
|
+
lowest_score = 1
|
32
|
+
|
33
|
+
begin
|
34
|
+
return if pixel == fresh_image[x,y]
|
35
|
+
rescue ChunkyPNG::OutOfBounds
|
36
|
+
# off the edge!
|
37
|
+
end
|
38
|
+
|
39
|
+
# try a bit in each direction to account for differences
|
40
|
+
[-2, -1, 0, 1, 2].each do |yd|
|
41
|
+
[-1, 0, 1].each do |xd|
|
42
|
+
begin
|
43
|
+
# to do based on more nuanced score
|
44
|
+
#score = Math.sqrt(
|
45
|
+
# (r(fresh_image[x+xd,y+yd]) - r(pixel)) ** 2 +
|
46
|
+
# (g(fresh_image[x+xd,y+yd]) - g(pixel)) ** 2 +
|
47
|
+
# (b(fresh_image[x+xd,y+yd]) - b(pixel)) ** 2
|
48
|
+
# ) / Math.sqrt(MAX ** 2 * 3)
|
49
|
+
|
50
|
+
return if pixel == fresh_image[x+xd,y+yd]
|
51
|
+
|
52
|
+
score = 1
|
53
|
+
|
54
|
+
lowest_score = score if score < lowest_score
|
55
|
+
rescue ChunkyPNG::OutOfBounds
|
56
|
+
# off the edge!
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@diff_index << [x,y,lowest_score] if lowest_score > 0
|
62
|
+
end
|
63
|
+
|
64
|
+
def diff_iterator
|
65
|
+
orig_image.height.times do |y|
|
66
|
+
orig_image.row(y).each_with_index do |pixel, x|
|
67
|
+
update_diff_index(x, y, pixel)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
return true
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns the numeric results of the diff of 2 images
|
75
|
+
def percentage_diff
|
76
|
+
return @percentage_changed if @percentage_changed
|
77
|
+
total_px = orig_image.pixels.length
|
78
|
+
changed_px = @diff_index.length
|
79
|
+
|
80
|
+
# to do based on more nuanced score
|
81
|
+
#changed_px = 0.0
|
82
|
+
#@diff_index.each do |x,y,score|
|
83
|
+
# could use the actual score
|
84
|
+
# changed_px += score
|
85
|
+
#end
|
86
|
+
@percentage_changed = ((changed_px.to_f*100) / total_px)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Saves the visual diff as a separate file
|
90
|
+
def save_visual_diff
|
91
|
+
x, y = @diff_index.map{ |xy| xy[0] }, @diff_index.map{ |xy| xy[1] }
|
92
|
+
diff_path = @orig_path.insert(-5, '_diff')
|
93
|
+
|
94
|
+
begin
|
95
|
+
fresh_image.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
|
96
|
+
rescue NoMethodError
|
97
|
+
puts "Both images are the same."
|
98
|
+
end
|
99
|
+
|
100
|
+
fresh_image.save(diff_path)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'phashion'
|
2
|
+
|
3
|
+
module Screenpress
|
4
|
+
module Compare
|
5
|
+
class Phashion
|
6
|
+
attr_reader :orig_image, :fresh_image, :difference
|
7
|
+
def initialize(orig_path, fresh_path)
|
8
|
+
@orig_image = ::Phashion::Image.new(orig_path)
|
9
|
+
@fresh_image = ::Phashion::Image.new(fresh_path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def difference
|
13
|
+
orig_print = orig_image.fingerprint
|
14
|
+
fresh_print = fresh_image.fingerprint
|
15
|
+
::Phashion.hamming_distance(orig_print, fresh_print)
|
16
|
+
end
|
17
|
+
|
18
|
+
def threshold
|
19
|
+
Screenpress.config.threshold || 15
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/screenpress/config.rb
CHANGED
@@ -39,7 +39,16 @@ module Screenpress
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def threshold
|
42
|
-
@threshold
|
42
|
+
@threshold
|
43
|
+
end
|
44
|
+
|
45
|
+
def comparator=val
|
46
|
+
@comparator = val
|
47
|
+
end
|
48
|
+
|
49
|
+
def comparator
|
50
|
+
@comparator ||= calc_comparator
|
51
|
+
@comparator
|
43
52
|
end
|
44
53
|
|
45
54
|
protected
|
@@ -53,6 +62,11 @@ module Screenpress
|
|
53
62
|
true
|
54
63
|
end
|
55
64
|
|
65
|
+
def calc_comparator
|
66
|
+
# TODO: see what's there
|
67
|
+
"bits"
|
68
|
+
end
|
69
|
+
|
56
70
|
def calc_root_string
|
57
71
|
return Rails.root.to_s if defined?(Rails)
|
58
72
|
return Padrino.root.to_s if defined?(Padrino)
|
data/lib/screenpress/saver.rb
CHANGED
@@ -28,8 +28,7 @@ module Screenpress
|
|
28
28
|
return false unless Screenpress::Saver::Proxy.save!(capybara.current_driver, page.driver, tmp_file)
|
29
29
|
|
30
30
|
# is it different?
|
31
|
-
|
32
|
-
if compare.same?
|
31
|
+
if same?(filename, tmp_file)
|
33
32
|
File.delete(tmp_file)
|
34
33
|
else
|
35
34
|
FileUtils.mv(tmp_file, filename)
|
@@ -41,6 +40,49 @@ module Screenpress
|
|
41
40
|
raise e
|
42
41
|
end
|
43
42
|
|
43
|
+
def same?(filename, tmp_file)
|
44
|
+
return !File.exists?(tmp_file) if !File.exists?(filename)
|
45
|
+
|
46
|
+
compare = comparator.new(filename, tmp_file)
|
47
|
+
if compare.respond_to?(:difference)
|
48
|
+
difference = compare.difference
|
49
|
+
if compare.respond_to?(:threshold)
|
50
|
+
threshold = compare.threshold
|
51
|
+
else
|
52
|
+
threshold = Screenpress.config.threshold || 0
|
53
|
+
end
|
54
|
+
if difference > threshold
|
55
|
+
puts " Screenpress #{filename} different: #{difference} > #{threshold}"
|
56
|
+
return false
|
57
|
+
else
|
58
|
+
puts " Screenpress #{filename} same: #{difference} <= #{threshold}"
|
59
|
+
return true
|
60
|
+
end
|
61
|
+
else
|
62
|
+
if compare.same?
|
63
|
+
return true
|
64
|
+
else
|
65
|
+
puts " Screenpress #{filename} different!"
|
66
|
+
return false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def comparator
|
72
|
+
case Screenpress.config.comparator
|
73
|
+
when "bits"
|
74
|
+
Screenpress::Compare::Bits
|
75
|
+
when "phashion", "phash"
|
76
|
+
Screenpress::Compare::Phashion
|
77
|
+
when "magick"
|
78
|
+
raise "ImageMagick comparator not yet implemented"
|
79
|
+
when "perceptualdiff"
|
80
|
+
raise "perceptualdiff comparator not yet implemented"
|
81
|
+
else
|
82
|
+
raise "Unknown comparator"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
44
86
|
def ensure_directory
|
45
87
|
folder = File.dirname(filename)
|
46
88
|
return if File.directory?(folder)
|
data/lib/screenpress/version.rb
CHANGED
data/screenpress.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: screenpress
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-02-27 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: capybara
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: phashion
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: bundler
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +139,8 @@ files:
|
|
123
139
|
- README.md
|
124
140
|
- Rakefile
|
125
141
|
- lib/screenpress.rb
|
126
|
-
- lib/screenpress/compare.rb
|
142
|
+
- lib/screenpress/compare/bits.rb
|
143
|
+
- lib/screenpress/compare/phashion.rb
|
127
144
|
- lib/screenpress/config.rb
|
128
145
|
- lib/screenpress/dsl.rb
|
129
146
|
- lib/screenpress/saver.rb
|
data/lib/screenpress/compare.rb
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
# based on: https://github.com/intridea/green_onion/blob/master/lib/green_onion/compare.rb
|
2
|
-
|
3
|
-
require "oily_png"
|
4
|
-
|
5
|
-
module Screenpress
|
6
|
-
class Compare
|
7
|
-
include ChunkyPNG::Color
|
8
|
-
|
9
|
-
attr_reader :orig_image, :fresh_image, :threshold
|
10
|
-
def initialize(orig_path, fresh_path, threshold)
|
11
|
-
@orig_path = orig_path
|
12
|
-
@fresh_path = fresh_path
|
13
|
-
@threshold ||= threshold
|
14
|
-
end
|
15
|
-
|
16
|
-
def same?
|
17
|
-
return !File.exists?(@fresh_path) if !File.exists?(@orig_path)
|
18
|
-
setup
|
19
|
-
|
20
|
-
return false unless diff_iterator
|
21
|
-
|
22
|
-
|
23
|
-
if percentage_diff > 0
|
24
|
-
puts "Image Percentage Different #{@orig_path}: #{percentage_diff}"
|
25
|
-
if percentage_diff > self.threshold
|
26
|
-
puts " Image different!"
|
27
|
-
return false
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
true
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def setup
|
37
|
-
return if @diff_index
|
38
|
-
@orig_image = ChunkyPNG::Image.from_file(@orig_path)
|
39
|
-
@fresh_image = ChunkyPNG::Image.from_file(@fresh_path)
|
40
|
-
@diff_index = []
|
41
|
-
end
|
42
|
-
|
43
|
-
|
44
|
-
# Pulled from Jeff Kreeftmeijer's post here: http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/
|
45
|
-
# Run through all of the pixels on both org image, and fresh image. Change the pixel color accordingly.
|
46
|
-
def update_diff_index(x, y, pixel)
|
47
|
-
lowest_score = 1
|
48
|
-
|
49
|
-
begin
|
50
|
-
return if pixel == fresh_image[x,y]
|
51
|
-
rescue ChunkyPNG::OutOfBounds
|
52
|
-
# off the edge!
|
53
|
-
end
|
54
|
-
|
55
|
-
# try a bit in each direction to account for differences
|
56
|
-
[-2, -1, 0, 1, 2].each do |yd|
|
57
|
-
[-1, 0, 1].each do |xd|
|
58
|
-
begin
|
59
|
-
# to do based on more nuanced score
|
60
|
-
#score = Math.sqrt(
|
61
|
-
# (r(fresh_image[x+xd,y+yd]) - r(pixel)) ** 2 +
|
62
|
-
# (g(fresh_image[x+xd,y+yd]) - g(pixel)) ** 2 +
|
63
|
-
# (b(fresh_image[x+xd,y+yd]) - b(pixel)) ** 2
|
64
|
-
# ) / Math.sqrt(MAX ** 2 * 3)
|
65
|
-
|
66
|
-
return if pixel == fresh_image[x+xd,y+yd]
|
67
|
-
|
68
|
-
score = 1
|
69
|
-
|
70
|
-
lowest_score = score if score < lowest_score
|
71
|
-
rescue ChunkyPNG::OutOfBounds
|
72
|
-
# off the edge!
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
@diff_index << [x,y,lowest_score] if lowest_score > 0
|
78
|
-
end
|
79
|
-
|
80
|
-
def diff_iterator
|
81
|
-
orig_image.height.times do |y|
|
82
|
-
orig_image.row(y).each_with_index do |pixel, x|
|
83
|
-
update_diff_index(x, y, pixel)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
return true
|
88
|
-
end
|
89
|
-
|
90
|
-
# Returns the numeric results of the diff of 2 images
|
91
|
-
def percentage_diff
|
92
|
-
return @percentage_changed if @percentage_changed
|
93
|
-
total_px = orig_image.pixels.length
|
94
|
-
changed_px = @diff_index.length
|
95
|
-
|
96
|
-
# to do based on more nuanced score
|
97
|
-
#changed_px = 0.0
|
98
|
-
#@diff_index.each do |x,y,score|
|
99
|
-
# could use the actual score
|
100
|
-
# changed_px += score
|
101
|
-
#end
|
102
|
-
@percentage_changed = ((changed_px.to_f*100) / total_px)
|
103
|
-
end
|
104
|
-
|
105
|
-
# Saves the visual diff as a separate file
|
106
|
-
def save_visual_diff
|
107
|
-
x, y = @diff_index.map{ |xy| xy[0] }, @diff_index.map{ |xy| xy[1] }
|
108
|
-
diff_path = @orig_path.insert(-5, '_diff')
|
109
|
-
|
110
|
-
begin
|
111
|
-
fresh_image.rect(x.min, y.min, x.max, y.max, ChunkyPNG::Color.rgb(0,255,0))
|
112
|
-
rescue NoMethodError
|
113
|
-
puts "Both images are the same."
|
114
|
-
end
|
115
|
-
|
116
|
-
fresh_image.save(diff_path)
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
end
|