screenpress 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -39,7 +39,16 @@ module Screenpress
39
39
  end
40
40
 
41
41
  def threshold
42
- @threshold ||= 0.1
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)
@@ -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
- compare = Screenpress::Compare.new(filename, tmp_file, Screenpress.config.threshold)
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)
@@ -1,3 +1,3 @@
1
1
  module Screenpress
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency "capybara"
22
22
  spec.add_dependency "oily_png"
23
23
 
24
+ spec.add_runtime_dependency("phashion")
25
+
24
26
  spec.add_development_dependency "bundler", "~> 1.3"
25
27
  spec.add_development_dependency "rake"
26
28
 
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.2.1
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: 2013-12-09 00:00:00.000000000 Z
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
@@ -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