imatcher 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6b74f4cc7e7d048a1bedabf6399d22c1752e029
4
- data.tar.gz: 490720e88565d39e81b8c1c0a6633dbb87a2a079
3
+ metadata.gz: 2ad15eab2eb3ec4656cafb23117199966625e18d
4
+ data.tar.gz: 3d15c721ce46ed7cbca79a0d9d4e310972ebcfc2
5
5
  SHA512:
6
- metadata.gz: 59a52908a3a8b6e03f49e4cff3113a25a8645d2b3c36d47d4f29febedfc7c30082a1d549cc6fd4895e11d1fb7e1cb905c1856056a73c1fba1b394c7d1ddba030
7
- data.tar.gz: f6392bc159c2e6ece9eb474645f763c35a329f4e75f42f53663aa4d25e71d65b52bee1c6971b5e16eb214e75e3342b6f54509e7483caf8a3f5c4fdff659db7cd
6
+ metadata.gz: b098cf87274c56a0089e795e686d6299ea91339d8bff948486ca25ea5a75e993fb1eb50d533416e2eddd18e035d1dc1330eb055e8a23ddb74e49d54c87f6b406
7
+ data.tar.gz: 11c76b5365728cfb495a764e15241d1aea897b8d1cf0642a0dceb870479ce2fc4f3bec87efd1c80ce59b12b8fc28d817cfda79013ec384cba7ed76bf7000635b
data/.gitignore CHANGED
@@ -23,6 +23,7 @@
23
23
  .settings
24
24
  .tmproj
25
25
  Thumbs.db
26
+ *.gem
26
27
 
27
28
  /.bundle/
28
29
  /.yardoc
data/.rubocop.yml CHANGED
@@ -32,9 +32,17 @@ Style/BlockDelimiters:
32
32
  Exclude:
33
33
  - 'spec/**/*.rb'
34
34
 
35
+ Style/ParallelAssignment:
36
+ Enabled: false
37
+
35
38
  Lint/AmbiguousRegexpLiteral:
36
39
  Enabled: false
37
40
 
38
41
  Metrics/MethodLength:
39
42
  Exclude:
40
43
  - 'spec/**/*.rb'
44
+
45
+ Metrics/LineLength:
46
+ max: 100
47
+ Exclude:
48
+ - 'spec/**/*.rb'
data/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
2
  cache: bundler
3
- matrix:
4
- include:
5
- - rvm: 2.2.2
6
- gemfile: gemfiles/rails42.gemfile
3
+ rvm:
4
+ - 2.2
5
+
6
+ notifications:
7
+ email: false
data/Gemfile CHANGED
@@ -2,8 +2,6 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- gem 'pry'
6
-
7
5
  local_gemfile = 'Gemfile.local'
8
6
 
9
7
  if File.exist?(local_gemfile)
data/README.md CHANGED
@@ -1,8 +1,9 @@
1
- # Imatcher
1
+ [![Build Status](https://travis-ci.org/teachbase/imatcher.svg?branch=master)](https://travis-ci.org/teachbase/imatcher)
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/imatcher`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ # Imatcher
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Compare PNG images in pure Ruby (uses [ChunkyPNG](https://github.com/wvanbergen/chunky_png)) using different algorithms.
6
+ This is an utility library for image regression testing.
6
7
 
7
8
  ## Installation
8
9
 
@@ -20,20 +21,76 @@ Or install it yourself as:
20
21
 
21
22
  $ gem install imatcher
22
23
 
24
+ ## Modes
25
+
26
+ Imatcher supports different ways (_modes_) of comparing images.
27
+
28
+ Source images used in examples:
29
+
30
+ <img src="https://raw.githubusercontent.com/teachbase/imatcher/master/spec/fixtures/a.png" width="300" />
31
+ <img src="https://raw.githubusercontent.com/teachbase/imatcher/master/spec/fixtures/b.png" width="300" />
32
+
33
+ ### Base (RGB) mode
34
+
35
+ Compare pixels by values, resulting score is a ratio of unequal pixels.
36
+ Resulting diff represents per-channel difference.
37
+
38
+ <img src="https://raw.githubusercontent.com/teachbase/imatcher/master/spec/fixtures/rgb_diff.png" width="300" />
39
+
40
+ ### Grayscale mode
41
+
42
+ Compare pixels as grayscale (by brightness and alpha), resulting score is a ratio of unequal pixels (with respect to provided tolerance).
43
+
44
+ Resulting diff contains grayscale version of the first image with different pixels highlighted in red and red bounding box.
45
+
46
+ <img src="https://raw.githubusercontent.com/teachbase/imatcher/master/spec/fixtures/grayscale_diff.png" width="300" />
47
+
48
+ ### Delta
49
+
50
+ Compare pixels using [Delta E](https://en.wikipedia.org/wiki/Color_difference) distance.
51
+ Resulting diff contains grayscale version of the first image with different pixels highlighted in red (with respect to diff score).
52
+
53
+ <img src="https://raw.githubusercontent.com/teachbase/imatcher/master/spec/fixtures/delta_diff.png" width="300" />
54
+
23
55
  ## Usage
24
56
 
25
- TODO: Write usage instructions here
57
+ ```ruby
58
+ # create new matcher with default threshold equals to 0
59
+ # and base (RGB) mode
60
+ cmp = Imatcher::Matcher.new
61
+ cmp.mode #=> Imatcher::Modes::RGB
26
62
 
27
- ## Development
63
+ # create matcher with specific threshold
64
+ cmp = Imatcher::Matcher.new threshold: 0.05
65
+ cmp.threshold #=> 0.05
28
66
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
67
+ # create zero-tolerance grayscale matcher
68
+ cmp = Imatcher::Matcher.new mode: :grayscale, tolerance: 0
69
+ cmp.mode #=> Imatcher::Modes::Grayscale
30
70
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
71
+ res = cmp.compare(path_1, path_2)
72
+ res #=> Imatcher::Result
32
73
 
33
- ## Contributing
74
+ res.match? #=> true
75
+
76
+ res.score #=> 0.0
77
+
78
+ # Return diff image object
79
+ res.difference_image #=> Imatcher::Image
34
80
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/imatcher.
81
+ res.difference_image.save(new_path)
82
+
83
+ # without explicit matcher
84
+ res = Imatcher.compare(path_1, path_2, options)
85
+
86
+ # equals to
87
+ res = Imatcher::Matcher.new(options).compare(path_1, path_2)
88
+
89
+ ```
90
+
91
+ ## Contributing
36
92
 
93
+ Bug reports and pull requests are welcome on GitHub at https://github.com/teachbase/imatcher.
37
94
 
38
95
  ## License
39
96
 
data/bin/setup CHANGED
@@ -4,5 +4,3 @@ IFS=$'\n\t'
4
4
  set -vx
5
5
 
6
6
  bundle install
7
-
8
- # Do any other automated setup that you need to do here
data/imatcher.gemspec CHANGED
@@ -15,7 +15,9 @@ Gem::Specification.new do |spec|
15
15
  spec.files = `git ls-files`.split($/)
16
16
  spec.require_paths = ["lib"]
17
17
 
18
- spec.add_development_dependency "bundler", "~> 1.11"
18
+ spec.add_dependency "chunky_png", "~> 1.3.5"
19
+
20
+ spec.add_development_dependency "simplecov", ">= 0.3.8"
19
21
  spec.add_development_dependency "rake", "~> 10.0"
20
22
  spec.add_development_dependency 'pry-byebug'
21
23
  spec.add_development_dependency "rspec", "~> 3.0"
data/lib/imatcher.rb CHANGED
@@ -1,4 +1,14 @@
1
1
  require "imatcher/version"
2
2
 
3
+ # Compare PNG images using different algorithms
3
4
  module Imatcher
5
+ class SizesMismatchError < StandardError
6
+ end
7
+
8
+ require 'imatcher/matcher'
9
+ require 'imatcher/color_methods'
10
+
11
+ def self.compare(path_a, path_b, options = {})
12
+ Matcher.new(options).compare(path_a, path_b)
13
+ end
4
14
  end
@@ -0,0 +1,11 @@
1
+ require 'chunky_png'
2
+
3
+ module Imatcher
4
+ module ColorMethods # :nodoc:
5
+ include ChunkyPNG::Color
6
+
7
+ def brightness(a)
8
+ 0.3 * r(a) + 0.59 * g(a) + 0.11 * b(a)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,47 @@
1
+ require 'imatcher/color_methods'
2
+
3
+ module Imatcher
4
+ # Extend ChunkyPNG::Image with some methods.
5
+ class Image < ChunkyPNG::Image
6
+ include ColorMethods
7
+
8
+ def each_pixel
9
+ height.times do |y|
10
+ row(y).each_with_index do |pixel, x|
11
+ yield(pixel, x, y)
12
+ end
13
+ end
14
+ end
15
+
16
+ def compare_each_pixel(image)
17
+ height.times do |y|
18
+ next if image.row(y) == row(y)
19
+ row(y).each_with_index do |pixel, x|
20
+ yield(pixel, image[x, y], x, y)
21
+ end
22
+ end
23
+ end
24
+
25
+ def to_grayscale
26
+ each_pixel do |pixel, x, y|
27
+ self[x, y] = grayscale(brightness(pixel).round)
28
+ end
29
+ self
30
+ end
31
+
32
+ def with_alpha(value)
33
+ each_pixel do |pixel, x, y|
34
+ self[x, y] = rgba(r(pixel), g(pixel), b(pixel), value)
35
+ end
36
+ self
37
+ end
38
+
39
+ def sizes_match?(image)
40
+ [width, height] == [image.width, image.height]
41
+ end
42
+
43
+ def render_bounds(left, bot, right, top)
44
+ rect(left, bot, right, top, rgb(255, 0, 0))
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module Imatcher
2
+ # Matcher contains information about compare mode
3
+ class Matcher
4
+ require 'imatcher/image'
5
+ require 'imatcher/result'
6
+ require 'imatcher/modes'
7
+
8
+ MODES = {
9
+ rgb: 'RGB',
10
+ delta: 'Delta',
11
+ grayscale: 'Grayscale'
12
+ }.freeze
13
+
14
+ attr_reader :threshold, :mode
15
+
16
+ def initialize(options = {})
17
+ mode_type = options.delete(:mode) || :rgb
18
+ @mode = Modes.const_get(MODES[mode_type]).new(options)
19
+ end
20
+
21
+ def compare(path_1, path_2)
22
+ a = Image.from_file(path_1)
23
+ b = Image.from_file(path_2)
24
+ raise SizesMismatchError,
25
+ "Size mismatch: first image size: " \
26
+ "#{a.width}x#{a.height}, " \
27
+ "second image size: " \
28
+ "#{b.width}x#{b.height}" unless a.sizes_match?(b)
29
+
30
+ mode.compare(a, b)
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ module Imatcher
2
+ module Modes # :nodoc:
3
+ require 'imatcher/modes/rgb'
4
+ require 'imatcher/modes/grayscale'
5
+ require 'imatcher/modes/delta'
6
+ end
7
+ end
@@ -0,0 +1,52 @@
1
+ module Imatcher
2
+ module Modes
3
+ class Base # :nodoc:
4
+ include ColorMethods
5
+
6
+ attr_reader :result, :threshold
7
+
8
+ def initialize(threshold: 0.0)
9
+ @threshold = threshold
10
+ @result = Result.new(self, threshold)
11
+ end
12
+
13
+ def compare(a, b)
14
+ result.image = a
15
+
16
+ b.compare_each_pixel(a) do |b_pixel, a_pixel, x, y|
17
+ next if pixels_equal?(b_pixel, a_pixel)
18
+ update_result(b_pixel, a_pixel, x, y)
19
+ end
20
+
21
+ result.score = score
22
+ result
23
+ end
24
+
25
+ def diff(bg, diff)
26
+ diff_image = background(bg)
27
+ diff_image.render_bounds(*calculate_bounds(diff))
28
+ diff.each do |pixels_pair|
29
+ pixels_diff(diff_image, *pixels_pair)
30
+ end
31
+ create_diff_image(bg, diff_image)
32
+ end
33
+
34
+ def score
35
+ @result.diff.length.to_f / @result.image.pixels.length
36
+ end
37
+
38
+ # rubocop:disable Metrics/AbcSize
39
+ def calculate_bounds(diff)
40
+ xmin, xmax, ymin, ymax = result.image.width, 0, result.image.height, 0
41
+ diff.each do |pixels_pair|
42
+ xmin = pixels_pair[2] if pixels_pair[2] < xmin
43
+ xmax = pixels_pair[2] if pixels_pair[2] > xmax
44
+ ymin = pixels_pair[3] if pixels_pair[3] < ymin
45
+ ymax = pixels_pair[3] if pixels_pair[3] > ymax
46
+ end
47
+
48
+ [xmin - 1, ymin - 1, xmax + 1, ymax + 1]
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,50 @@
1
+ module Imatcher
2
+ module Modes # :nodoc:
3
+ require 'imatcher/modes/base'
4
+
5
+ # Compare pixels using Delta E distance.
6
+ class Delta < Base
7
+ def initialize(threshold: 0.0)
8
+ @threshold = threshold
9
+ @result = Result.new(self, threshold)
10
+ @delta_score = 0.0
11
+ end
12
+
13
+ private
14
+
15
+ def pixels_equal?(a, b)
16
+ a == b
17
+ end
18
+
19
+ def update_result(a, b, x, y)
20
+ d = euclid(a, b) / (MAX * Math.sqrt(3))
21
+ @result.diff << [a, b, x, y, d]
22
+ @delta_score += d
23
+ end
24
+
25
+ def background(bg)
26
+ Image.new(bg.width, bg.height, WHITE).with_alpha(0)
27
+ end
28
+
29
+ def euclid(a, b)
30
+ Math.sqrt(
31
+ (r(a) - r(b))**2 +
32
+ (g(a) - g(b))**2 +
33
+ (b(a) - b(b))**2
34
+ )
35
+ end
36
+
37
+ def create_diff_image(bg, diff_image)
38
+ bg.to_grayscale.compose!(diff_image, 0, 0)
39
+ end
40
+
41
+ def pixels_diff(d, *_args, x, y, a)
42
+ d[x, y] = rgba(MAX, 0, 0, (a * MAX).round)
43
+ end
44
+
45
+ def score
46
+ @delta_score / result.image.pixels.length
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,48 @@
1
+ module Imatcher
2
+ module Modes # :nodoc:
3
+ require 'imatcher/modes/base'
4
+
5
+ # Compare pixels by alpha and brightness.
6
+ #
7
+ # Options:
8
+ # - tolerance - defines the maximum allowed difference for alpha/brightness
9
+ # (default value is 16)
10
+ class Grayscale < Base
11
+ DEFAULT_TOLERANCE = 16
12
+
13
+ attr_reader :tolerance
14
+
15
+ def initialize(options)
16
+ @tolerance = options.delete(:tolerance) || DEFAULT_TOLERANCE
17
+ super(options)
18
+ end
19
+
20
+ def pixels_equal?(a, b)
21
+ alpha = color_similar?(a(a), a(b))
22
+ brightness = color_similar?(brightness(a), brightness(b))
23
+ brightness && alpha
24
+ end
25
+
26
+ def update_result(a, b, x, y)
27
+ @result.diff << [a, b, x, y]
28
+ end
29
+
30
+ def background(bg)
31
+ bg.to_grayscale
32
+ end
33
+
34
+ def pixels_diff(d, _a, _b, x, y)
35
+ d[x, y] = rgb(255, 0, 0)
36
+ end
37
+
38
+ def create_diff_image(_bg, diff_image)
39
+ diff_image
40
+ end
41
+
42
+ def color_similar?(a, b)
43
+ d = (a - b).abs
44
+ d <= tolerance
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,33 @@
1
+ module Imatcher
2
+ module Modes # :nodoc:
3
+ require 'imatcher/modes/base'
4
+
5
+ # Compare pixels by values.
6
+ # Resulting image contains per-channel differences.
7
+ class RGB < Base
8
+ def pixels_equal?(a, b)
9
+ a == b
10
+ end
11
+
12
+ def update_result(a, b, x, y)
13
+ @result.diff << [a, b, x, y]
14
+ end
15
+
16
+ def background(bg)
17
+ Image.new(bg.width, bg.height, BLACK)
18
+ end
19
+
20
+ def create_diff_image(bg, diff_image)
21
+ bg.to_grayscale.compose!(diff_image, 0, 0)
22
+ end
23
+
24
+ def pixels_diff(d, a, b, x, y)
25
+ d[x, y] = rgb(
26
+ (r(a) - r(b)).abs,
27
+ (g(a) - g(b)).abs,
28
+ (b(a) - b(b)).abs
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module Imatcher
2
+ # Object containing comparison score and diff image
3
+ class Result
4
+ attr_accessor :score, :image
5
+ attr_reader :diff, :mode, :threshold
6
+
7
+ def initialize(mode, threshold)
8
+ @score = 0.0
9
+ @diff = []
10
+ @threshold = threshold
11
+ @mode = mode
12
+ end
13
+
14
+ def difference_image
15
+ @diff_image ||= mode.diff(image, diff)
16
+ end
17
+
18
+ # Returns true iff score less or equals to threshold
19
+ def match?
20
+ score <= threshold
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Imatcher # :nodoc:
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.1".freeze
3
3
  end
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -4,8 +4,4 @@ describe Imatcher do
4
4
  it 'has a version number' do
5
5
  expect(Imatcher::VERSION).not_to be nil
6
6
  end
7
-
8
- it 'does something useful' do
9
- expect(false).to eq(true)
10
- end
11
7
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe Imatcher::Modes::Delta do
4
+ let(:path_1) { image_path "a" }
5
+ let(:path_2) { image_path "darker" }
6
+ subject { Imatcher.compare(path_1, path_2, options) }
7
+
8
+ let(:options) { { mode: :delta } }
9
+
10
+ context "with similar images" do
11
+ it "score around 0.094" do
12
+ expect(subject.score).to be_within(0.0005).of(0.094)
13
+ end
14
+
15
+ context "with custom threshold" do
16
+ subject { Imatcher.compare(path_1, path_2, options).match? }
17
+
18
+ context "below score" do
19
+ let(:options) { { mode: :delta, threshold: 0.01 } }
20
+
21
+ it { expect(subject).to eq false }
22
+ end
23
+
24
+ context "above score" do
25
+ let(:options) { { mode: :delta, threshold: 0.1 } }
26
+
27
+ it { expect(subject).to eq true }
28
+ end
29
+ end
30
+ end
31
+
32
+ context "with different images" do
33
+ let(:path_2) { image_path "b" }
34
+
35
+ it "score around 0.0195" do
36
+ expect(subject.score).to be_within(0.0005).of(0.0195)
37
+ end
38
+
39
+ it "creates correct difference image" do
40
+ expect(subject.difference_image).to eq(Imatcher::Image.from_file(image_path("delta_diff")))
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Imatcher::Modes::Grayscale do
4
+ let(:path_1) { image_path "a" }
5
+ let(:path_2) { image_path "darker" }
6
+ subject { Imatcher.compare(path_1, path_2, options) }
7
+
8
+ let(:options) { { mode: :grayscale } }
9
+
10
+ context "darker image" do
11
+ it "score around 0.7" do
12
+ expect(subject.score).to be_within(0.05).of(0.75)
13
+ end
14
+ end
15
+
16
+ context "different images" do
17
+ let(:path_2) { image_path "b" }
18
+
19
+ it "score around 0.02" do
20
+ expect(subject.score).to be_within(0.0005).of(0.009)
21
+ end
22
+
23
+ it "creates correct difference image" do
24
+ expect(subject.difference_image).to eq(Imatcher::Image.from_file(image_path("grayscale_diff")))
25
+ end
26
+ end
27
+
28
+ context "with zero tolerance" do
29
+ let(:options) { { mode: :grayscale, tolerance: 0 } }
30
+
31
+ context "darker image" do
32
+ it "score equals to 1" do
33
+ expect(subject.score).to eq 1.0
34
+ end
35
+ end
36
+
37
+ context "different image" do
38
+ let(:path_2) { image_path "b" }
39
+
40
+ it "score around 0.97" do
41
+ expect(subject.score).to be_within(0.005).of(0.97)
42
+ end
43
+ end
44
+
45
+ context "equal image" do
46
+ let(:path_2) { image_path "a" }
47
+
48
+ it "score equals to 0" do
49
+ expect(subject.score).to eq 0
50
+ end
51
+ end
52
+ end
53
+
54
+ context "with small tolerance" do
55
+ let(:options) { { mode: :grayscale, tolerance: 8 } }
56
+
57
+ context "darker image" do
58
+ it "score around 0.9" do
59
+ expect(subject.score).to be_within(0.005).of(0.9)
60
+ end
61
+ end
62
+
63
+ context "different image" do
64
+ let(:path_2) { image_path "b" }
65
+
66
+ it "score around 0.027" do
67
+ expect(subject.score).to be_within(0.0005).of(0.027)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Imatcher::Modes::RGB do
4
+ let(:path_1) { image_path "a" }
5
+ let(:path_2) { image_path "darker" }
6
+ subject { Imatcher.compare(path_1, path_2, options) }
7
+ let(:options) { {} }
8
+
9
+ context "with similar images" do
10
+ it "score equals to 1" do
11
+ expect(subject.score).to eq 1
12
+ end
13
+ end
14
+
15
+ context "with different images" do
16
+ let(:path_2) { image_path "b" }
17
+
18
+ it "score around 0.97" do
19
+ expect(subject.score).to be_within(0.005).of(0.97)
20
+ end
21
+
22
+ it "creates correct difference image" do
23
+ expect(subject.difference_image).to eq(Imatcher::Image.from_file(image_path("rgb_diff")))
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+
3
+ describe Imatcher::Matcher do
4
+ describe "new" do
5
+ subject { Imatcher::Matcher.new(options) }
6
+
7
+ context "without options" do
8
+ let(:options) { {} }
9
+
10
+ it { expect(subject.mode.threshold).to eq 0 }
11
+ it { expect(subject.mode).to be_a Imatcher::Modes::RGB }
12
+ end
13
+
14
+ context "with custom threshold" do
15
+ let(:options) { { threshold: 0.1 } }
16
+
17
+ it { expect(subject.mode.threshold).to eq 0.1 }
18
+ end
19
+
20
+ context "with custom options" do
21
+ let(:options) { { mode: :grayscale, tolerance: 0 } }
22
+
23
+ it { expect(subject.mode.tolerance).to eq 0 }
24
+ end
25
+
26
+ context "with custom mode" do
27
+ let(:options) { { mode: :delta } }
28
+
29
+ it { expect(subject.mode).to be_a Imatcher::Modes::Delta }
30
+ end
31
+ end
32
+
33
+ describe "compare" do
34
+ let(:path_1) { image_path "very_small" }
35
+ let(:path_2) { image_path "very_small" }
36
+ subject { Imatcher::Matcher.new.compare(path_1, path_2) }
37
+
38
+ it { expect(subject).to be_a Imatcher::Result }
39
+
40
+ context "when sizes mismatch" do
41
+ let(:path_2) { image_path "small" }
42
+ it { expect { subject }.to raise_error(Imatcher::SizesMismatchError) }
43
+ end
44
+ end
45
+ end
data/spec/spec_helper.rb CHANGED
@@ -2,6 +2,13 @@ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
2
 
3
3
  require 'rspec'
4
4
  require 'pry-byebug'
5
+
6
+ if ENV['COVER']
7
+ require 'simplecov'
8
+ SimpleCov.root File.join(File.dirname(__FILE__), '..')
9
+ SimpleCov.start
10
+ end
11
+
5
12
  require 'imatcher'
6
13
 
7
14
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -9,3 +16,7 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
9
16
  RSpec.configure do |config|
10
17
  config.mock_with :rspec
11
18
  end
19
+
20
+ def image_path(name)
21
+ "#{File.dirname(__FILE__)}/fixtures/#{name}.png"
22
+ end
metadata CHANGED
@@ -1,29 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: imatcher
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - palkan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-15 00:00:00.000000000 Z
11
+ date: 2016-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: chunky_png
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.11'
20
- type: :development
19
+ version: 1.3.5
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.11'
26
+ version: 1.3.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: simplecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.3.8
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.3.8
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -85,8 +99,29 @@ files:
85
99
  - bin/setup
86
100
  - imatcher.gemspec
87
101
  - lib/imatcher.rb
102
+ - lib/imatcher/color_methods.rb
103
+ - lib/imatcher/image.rb
104
+ - lib/imatcher/matcher.rb
105
+ - lib/imatcher/modes.rb
106
+ - lib/imatcher/modes/base.rb
107
+ - lib/imatcher/modes/delta.rb
108
+ - lib/imatcher/modes/grayscale.rb
109
+ - lib/imatcher/modes/rgb.rb
110
+ - lib/imatcher/result.rb
88
111
  - lib/imatcher/version.rb
112
+ - spec/fixtures/a.png
113
+ - spec/fixtures/b.png
114
+ - spec/fixtures/darker.png
115
+ - spec/fixtures/delta_diff.png
116
+ - spec/fixtures/grayscale_diff.png
117
+ - spec/fixtures/rgb_diff.png
118
+ - spec/fixtures/small.png
119
+ - spec/fixtures/very_small.png
89
120
  - spec/imatcher_spec.rb
121
+ - spec/integrations/delta_spec.rb
122
+ - spec/integrations/grayscale_spec.rb
123
+ - spec/integrations/rgb_spec.rb
124
+ - spec/matcher_spec.rb
90
125
  - spec/spec_helper.rb
91
126
  homepage: http://github.com/teachbase/imatcher
92
127
  licenses: