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.
@@ -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