pixmatch 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2011 Art.sy
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
data/README.rdoc ADDED
@@ -0,0 +1,86 @@
1
+ = Pixmatch
2
+
3
+ Pixmatch REST API client library for TinEye[http://www.tineye.com/] reverse-image search.
4
+
5
+ == Using
6
+
7
+ gem install pixmatch
8
+
9
+ == Example
10
+
11
+ require 'rubygems'
12
+ require 'pixmatch'
13
+
14
+ Pixmatch.configure do |config|
15
+ config.username = 'username'
16
+ config.password = 'password'
17
+ config.url = 'api.tineye.com'
18
+ end
19
+
20
+ # ping the server
21
+ response = Pixmatch.ping()
22
+ puts response['status']
23
+
24
+ # count the number of images in the collection
25
+ count = Pixmatch.count()
26
+
27
+ # add an image
28
+ Pixmatch.add('images/mona-lisa.jpg')
29
+ Pixmatch.add(File.new('images/mona-lisa.jpg')
30
+
31
+ # add a collection of images
32
+ Pixmatch.add(Dir.glob('images/*.jpg'))
33
+
34
+ # list images
35
+ images = Pixmatch.list()
36
+ images.each { |filename| puts filename }
37
+
38
+ # delete an image
39
+ Pixmatch.delete('mona-lisa.jpg')
40
+
41
+ # delete an array of images
42
+ Pixmatch.delete([ 'mona-lisa.jpg', 'mona-lisa-botero.jpg' ])
43
+
44
+ # search
45
+ found = Pixmatch.search('images/mona-lisa.jpg')
46
+ found.each { |find|
47
+ puts "#{find['filename']}: #{find['score']}"
48
+ }
49
+
50
+ == Contributing
51
+
52
+ * Fork the project
53
+ * Copy 'config/pixmatch.yml.default' to 'config/pixmatch.yml'. Edit your pixmatch API credentials as follows.
54
+ test:
55
+ <<: *settings
56
+ username: '<your username>'
57
+ password: '<your password>'
58
+ endpoint: 'http://<your url>.tineye.com'
59
+ * Run 'bundle install'
60
+ * Test with 'rspec spec'
61
+ * Send pull requests.
62
+
63
+ == Copyright
64
+
65
+ Copyright (c) 2011 Art.sy
66
+
67
+ Permission is hereby granted, free of charge, to any person obtaining
68
+ a copy of this software and associated documentation files (the
69
+ "Software"), to deal in the Software without restriction, including
70
+ without limitation the rights to use, copy, modify, merge, publish,
71
+ distribute, sublicense, and/or sell copies of the Software, and to
72
+ permit persons to whom the Software is furnished to do so, subject to
73
+ the following conditions:
74
+
75
+ The above copyright notice and this permission notice shall be
76
+ included in all copies or substantial portions of the Software.
77
+
78
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
79
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
80
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
81
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
82
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
83
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
84
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
85
+
86
+
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../request', __FILE__)
2
+
3
+ # Adapted from the Ruby Twitter gem.
4
+ # @see https://github.com/jnunemaker/twitter
5
+ module Pixmatch
6
+ # @private
7
+ class API
8
+ # @private
9
+ attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
10
+
11
+ # Creates a new API
12
+ def initialize(options = {})
13
+ options = Pixmatch.options.merge(options)
14
+ Configuration::VALID_OPTIONS_KEYS.each do |key|
15
+ send("#{key}=", options[key])
16
+ end
17
+ end
18
+
19
+ include Request
20
+ end
21
+ end
@@ -0,0 +1,14 @@
1
+ module Pixmatch
2
+ class Client
3
+ module Add
4
+ # Index and Add a list of images to your collection.
5
+ # @param files [Array] Array of File or String objects.
6
+ def add(files)
7
+ files = [ files ] if (files.is_a?(String) || files.is_a?(File))
8
+ files_hash = { }
9
+ files.each { |f| files_hash["images[#{files_hash.size}]"] = f.is_a?(File) ? f : File.new(f, "rb") }
10
+ request(:post, 'rest', { method: :add }, { payload: files_hash })
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Pixmatch
2
+ class Client
3
+ module Count
4
+ # Get the number of items currently in the collection.
5
+ # @return Number of items currently in the collection.
6
+ def count
7
+ response = request(:get, 'rest', { method: :count })
8
+ result = response['result']
9
+ raise "Missing result in response." if result.nil?
10
+ raise "Invalid result in response (#{result.class.name})." if ! result.is_a?(Array)
11
+ raise "Invalid count in result response (#{result.size})." if result.size != 1
12
+ result[0].to_i
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ module Pixmatch
2
+ class Client
3
+ module Delete
4
+ # Given a list of image filenames, delete the images from the collection.
5
+ # @param files [Array] Array of file names.
6
+ def delete(filenames)
7
+ filenames = [ filenames ] if filenames.is_a?(String)
8
+ filenames_hash = { }
9
+ filenames.each { |f| filenames_hash["filenames[#{filenames_hash.size}]"] = f }
10
+ request(:post, 'rest', { method: :delete }, { payload: filenames_hash })
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module Pixmatch
2
+ class Client
3
+ module List
4
+ # List the contents of the collection.
5
+ # @param offset [Integer] Offset to start at, default is zero.
6
+ # @param limit [Integer] Limit number of results, default is zero (all results).
7
+ def list(offset = 0, limit = 0)
8
+ response = request(:get, 'rest', { method: 'list', offset: offset, limit: limit })
9
+ result = response['result']
10
+ raise "Missing result in response." if result.nil?
11
+ raise "Invalid result in response (#{result.class.name})." if ! result.is_a?(Array)
12
+ result
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ module Pixmatch
2
+ class Client
3
+ module Ping
4
+ # Check whether the PixMatch server is running.
5
+ def ping
6
+ request(:get, 'rest', { method: :ping })
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ module Pixmatch
2
+ class Client
3
+ module Search
4
+ # Given an image, search against our collection and return any matches with corresponding scores.
5
+ # @param image [File or String] The image file object that will be searched for.
6
+ # @param options [Hash] The following options.
7
+ # * min_score [Integer] The minimum score that should be returned, defaults to 0. Should be between 0 and 100 (inclusive).
8
+ # * max_num_matches [Integer] The maximum number of matches that should be returned, defaults to 10. A value of -1 indicates no limit.
9
+ # * check_horizontal_flip [Boolean] Indicates whether the search incorporates checking for horizontal flips, defaults to true.
10
+ # @return Array of { score, filename } hashes.
11
+ def search(image, options = {})
12
+ payload = { "image" => image.is_a?(File) ? image : File.new(image, "rb") }
13
+ response = request(:post, 'rest', { method: 'search' }.merge(options), { payload: payload })
14
+ result = response['result']
15
+ raise "Missing result in response." if result.nil?
16
+ raise "Invalid result in response (#{result.class.name})." if ! result.is_a?(Array)
17
+ result
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ # Adapted from the Ruby Twitter gem.
2
+ # @see https://github.com/jnunemaker/twitter
3
+ module Pixmatch
4
+ # Wrapper for the Pixmatch REST API
5
+ class Client < API
6
+ Dir[File.expand_path('../client/*.rb', __FILE__)].each { |f| require f }
7
+
8
+ include Pixmatch::Client::Ping
9
+ include Pixmatch::Client::Count
10
+ include Pixmatch::Client::Add
11
+ include Pixmatch::Client::List
12
+ include Pixmatch::Client::Delete
13
+ include Pixmatch::Client::Search
14
+ end
15
+ end
@@ -0,0 +1,49 @@
1
+ # Adapted from the Ruby Twitter gem.
2
+ # @see https://github.com/jnunemaker/twitter
3
+ module Pixmatch
4
+ # Defines constants and methods related to configuration.
5
+ module Configuration
6
+ # An array of valid keys in the options hash when configuring a {Flixated::API}.
7
+ VALID_OPTIONS_KEYS = [
8
+ :username,
9
+ :password,
10
+ :endpoint
11
+ ].freeze
12
+
13
+ # By default, don't set a username.
14
+ DEFAULT_USERNAME = nil.freeze
15
+
16
+ # By default, don't set a password.
17
+ DEFAULT_PASSWORD = nil.freeze
18
+
19
+ # The endpoint that will be used to connect if none is set.
20
+ DEFAULT_ENDPOINT = 'https://api.tineye.com'.freeze
21
+
22
+ # @private
23
+ attr_accessor(*VALID_OPTIONS_KEYS)
24
+
25
+ # When this module is extended, set all configuration options to their default values.
26
+ def self.extended(base)
27
+ base.reset
28
+ end
29
+
30
+ # Convenience method to allow configuration options to be set in a block.
31
+ def configure
32
+ yield self
33
+ end
34
+
35
+ # Create a hash of options and their values.
36
+ def options
37
+ VALID_OPTIONS_KEYS.inject({}) do |option,key|
38
+ option.merge!(key => send(key))
39
+ end
40
+ end
41
+
42
+ # Reset all configuration options to default.
43
+ def reset
44
+ self.username = DEFAULT_USERNAME
45
+ self.password = DEFAULT_PASSWORD
46
+ self.endpoint = DEFAULT_ENDPOINT
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ module Pixmatch
2
+ # Custom error class for rescuing from all known Pixmatch errors.
3
+ class Error < StandardError
4
+ attr_accessor :status, :method, :detail
5
+
6
+ def initialize(json)
7
+ @status = json['status']
8
+ @method = json['method']
9
+ @error = json['error']
10
+ @result = json['result']
11
+ end
12
+
13
+ def to_s
14
+ s = @error.nil? ? 'Unexpected Error' : @error.join('\r\n')
15
+ s += ("\r\n " + @result.join('\r\n ')) if @result
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'uri'
2
+ require 'rest_client'
3
+
4
+ module Pixmatch
5
+ module Request
6
+ private
7
+
8
+ def request(http_method, path, query_params = {}, data_params = {})
9
+ capture RestClient::Request.new({
10
+ method: http_method,
11
+ url: "#{endpoint}/#{paramify(path, query_params)}",
12
+ user: username,
13
+ password: password
14
+ }.merge(data_params)).execute
15
+ end
16
+
17
+ def capture(response)
18
+ json = Utils.parse_json(response)
19
+ Utils.handle_error(json)
20
+ json
21
+ end
22
+
23
+ def paramify(path, params)
24
+ URI.encode("#{path}/?#{params.map { |k,v| "#{k}=#{v}" }.join('&')}")
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,17 @@
1
+ require 'hashie'
2
+ require 'yajl'
3
+
4
+ module Pixmatch
5
+ # @private
6
+ module Utils
7
+ private
8
+ def self.handle_error(json_response)
9
+ raise Pixmatch::Error.new(json_response) if (json_response['status'] != 'ok')
10
+ end
11
+
12
+ # Parses JSON and returns a Hashie::Mash
13
+ def self.parse_json(json)
14
+ Hashie::Mash.new(Yajl::Parser.new.parse(json))
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module Pixmatch
2
+ VERSION = '0.1.0'
3
+ end
data/lib/pixmatch.rb ADDED
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../pixmatch/version', __FILE__)
2
+ require File.expand_path('../pixmatch/configuration', __FILE__)
3
+ require File.expand_path('../pixmatch/utils', __FILE__)
4
+ require File.expand_path('../pixmatch/error', __FILE__)
5
+ require File.expand_path('../pixmatch/api', __FILE__)
6
+ require File.expand_path('../pixmatch/client', __FILE__)
7
+
8
+ # Adapted from the Ruby Twitter gem.
9
+ # @see https://github.com/jnunemaker/twitter
10
+ module Pixmatch
11
+ extend Configuration
12
+
13
+ # Alias for pixmatch::Client.new
14
+ #
15
+ # @return {pixmatch::Client}
16
+ def self.client(options = {})
17
+ Pixmatch::Client.new(options)
18
+ end
19
+
20
+ # Delegate to pixmatch::Client
21
+ def self.method_missing(method, *args, &block)
22
+ return super unless client.respond_to?(method)
23
+ client.send(method, *args, &block)
24
+ end
25
+
26
+ # Delegate to pixmatch::Client
27
+ def self.respond_to?(method)
28
+ return client.respond_to?(method) || super
29
+ end
30
+ end
@@ -0,0 +1,87 @@
1
+ require 'yaml'
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ describe "Pixmatch" do
6
+ before(:each) do
7
+ Pixmatch.configure do |config|
8
+ pixmatch_yml = File.join(File.dirname(__FILE__), '../config/pixmatch.yml')
9
+ pixmatch_yml = File.join(File.dirname(__FILE__), '../config/pixmatch.yml.default') if ! File.exists?(pixmatch_yml)
10
+ raise "missing config/pixmatch.yml" if ! File.exists?(pixmatch_yml)
11
+ pixmatch_config = YAML.load_file(pixmatch_yml)['test']
12
+ config.username = pixmatch_config['username']
13
+ config.password = pixmatch_config['password']
14
+ config.endpoint = pixmatch_config['endpoint']
15
+ end
16
+ end
17
+ describe "methods" do
18
+ it "ping" do
19
+ response = Pixmatch.ping()
20
+ response['status'].should == "ok"
21
+ response['method'].should == "ping"
22
+ end
23
+ it "count" do
24
+ count = Pixmatch.count()
25
+ count.is_a?(Integer).should be_true
26
+ count.should >= 0
27
+ end
28
+ it "add with one path" do
29
+ response = Pixmatch.add(File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg'))
30
+ response['status'].should == "ok"
31
+ response['method'].should == "add"
32
+ end
33
+ it "add with one path as an array" do
34
+ response = Pixmatch.add([ File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg') ])
35
+ response['status'].should == "ok"
36
+ response['method'].should == "add"
37
+ end
38
+ it "add with one File object" do
39
+ response = Pixmatch.add(File.new(File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg')))
40
+ response['status'].should == "ok"
41
+ response['method'].should == "add"
42
+ end
43
+ it "add with one File object as an array" do
44
+ response = Pixmatch.add([ File.new(File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg')) ])
45
+ response['status'].should == "ok"
46
+ response['method'].should == "add"
47
+ end
48
+ it "add with an array of File objects" do
49
+ response = Pixmatch.add(Dir.glob(File.join(File.dirname(__FILE__), 'assets/*.jpg')))
50
+ response['status'].should == "ok"
51
+ response['method'].should == "add"
52
+ end
53
+ it "list" do
54
+ result = Pixmatch.list()
55
+ result.is_a?(Array).should be_true
56
+ result.size.should >= 0
57
+ end
58
+ it "delete with one name" do
59
+ Pixmatch.add([ File.new(File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg')) ])
60
+ count = Pixmatch.count
61
+ response = Pixmatch.delete('mona-lisa.jpg')
62
+ response['status'].should == "ok"
63
+ response['method'].should == "delete"
64
+ Pixmatch.count.should == count - 1
65
+ end
66
+ it "delete an array of names" do
67
+ Pixmatch.add(Dir.glob(File.join(File.dirname(__FILE__), 'assets/*.jpg')))
68
+ count = Pixmatch.count
69
+ filenames = Dir.glob(File.join(File.dirname(__FILE__), 'assets/*.jpg')).map { |f| File.basename(f) }
70
+ response = Pixmatch.delete(filenames)
71
+ response['status'].should == "ok"
72
+ response['method'].should == "delete"
73
+ Pixmatch.count.should == count - filenames.size
74
+ end
75
+ it "search" do
76
+ Pixmatch.add(Dir.glob(File.join(File.dirname(__FILE__), 'assets/*.jpg')))
77
+ response = Pixmatch.search(File.join(File.dirname(__FILE__), 'assets/mona-lisa.jpg'))
78
+ response.is_a?(Array).should be_true
79
+ response.size.should >= 0
80
+ response.each { |result|
81
+ result.is_a?(Hash).should be_true
82
+ result.has_key?('score').should be_true
83
+ result.has_key?('filename').should be_true
84
+ }
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,11 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'rspec'
5
+ require 'pixmatch'
6
+
7
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
8
+
9
+ RSpec.configure do |config|
10
+
11
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pixmatch
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ prerelease: false
10
+ platform: ruby
11
+ authors:
12
+ - Daniel Doubrovkine
13
+ autorequire: !!null
14
+ bindir: bin
15
+ cert_chain: []
16
+ date: 2011-04-13 00:00:00.000000000 -04:00
17
+ default_executable: !!null
18
+ dependencies:
19
+ - !ruby/object:Gem::Dependency
20
+ name: rest-client
21
+ requirement: &86264460 !ruby/object:Gem::Requirement
22
+ none: false
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.1
27
+ segments:
28
+ - 1
29
+ - 6
30
+ - 1
31
+ type: :runtime
32
+ prerelease: false
33
+ version_requirements: *86264460
34
+ - !ruby/object:Gem::Dependency
35
+ name: yajl-ruby
36
+ requirement: &86264070 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ~>
40
+ - !ruby/object:Gem::Version
41
+ version: 0.8.1
42
+ segments:
43
+ - 0
44
+ - 8
45
+ - 1
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *86264070
49
+ - !ruby/object:Gem::Dependency
50
+ name: hashie
51
+ requirement: &86263680 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ~>
55
+ - !ruby/object:Gem::Version
56
+ version: 1.0.0
57
+ segments:
58
+ - 1
59
+ - 0
60
+ - 0
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: *86263680
64
+ - !ruby/object:Gem::Dependency
65
+ name: rspec
66
+ requirement: &86263290 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ~>
70
+ - !ruby/object:Gem::Version
71
+ version: 2.5.0
72
+ segments:
73
+ - 2
74
+ - 5
75
+ - 0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: *86263290
79
+ - !ruby/object:Gem::Dependency
80
+ name: bundler
81
+ requirement: &86262900 !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ~>
85
+ - !ruby/object:Gem::Version
86
+ version: 1.0.10
87
+ segments:
88
+ - 1
89
+ - 0
90
+ - 10
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: *86262900
94
+ - !ruby/object:Gem::Dependency
95
+ name: jeweler
96
+ requirement: &86262510 !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 1.5.2
102
+ segments:
103
+ - 1
104
+ - 5
105
+ - 2
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: *86262510
109
+ - !ruby/object:Gem::Dependency
110
+ name: yard
111
+ requirement: &86262120 !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ~>
115
+ - !ruby/object:Gem::Version
116
+ version: 0.6.4
117
+ segments:
118
+ - 0
119
+ - 6
120
+ - 4
121
+ type: :development
122
+ prerelease: false
123
+ version_requirements: *86262120
124
+ description: Pixmatch REST API client library for Ruby
125
+ email: dblock@dblock.org
126
+ executables: []
127
+ extensions: []
128
+ extra_rdoc_files:
129
+ - LICENSE.txt
130
+ - README.rdoc
131
+ files:
132
+ - lib/pixmatch.rb
133
+ - lib/pixmatch/api.rb
134
+ - lib/pixmatch/client.rb
135
+ - lib/pixmatch/client/add.rb
136
+ - lib/pixmatch/client/count.rb
137
+ - lib/pixmatch/client/delete.rb
138
+ - lib/pixmatch/client/list.rb
139
+ - lib/pixmatch/client/ping.rb
140
+ - lib/pixmatch/client/search.rb
141
+ - lib/pixmatch/configuration.rb
142
+ - lib/pixmatch/error.rb
143
+ - lib/pixmatch/request.rb
144
+ - lib/pixmatch/utils.rb
145
+ - lib/pixmatch/version.rb
146
+ - LICENSE.txt
147
+ - README.rdoc
148
+ - spec/pixmatch_spec.rb
149
+ - spec/spec_helper.rb
150
+ has_rdoc: true
151
+ homepage: http://github.com/dblock/pixmatch
152
+ licenses:
153
+ - MIT
154
+ post_install_message: !!null
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ none: false
160
+ requirements:
161
+ - - ! '>='
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ segments:
165
+ - 0
166
+ hash: -137474991
167
+ required_rubygems_version: !ruby/object:Gem::Requirement
168
+ none: false
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: '0'
173
+ segments:
174
+ - 0
175
+ requirements: []
176
+ rubyforge_project: !!null
177
+ rubygems_version: 1.3.7
178
+ signing_key: !!null
179
+ specification_version: 3
180
+ summary: Pixmatch REST API client library for Ruby
181
+ test_files:
182
+ - spec/pixmatch_spec.rb
183
+ - spec/spec_helper.rb