borealis 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7dc6e8b735da4b63a7edf43f7b2cc0964a67eff1
4
+ data.tar.gz: a98909c6d6398b291e8cabecb0ed7eb3a7d1e584
5
+ SHA512:
6
+ metadata.gz: 806fc46d3831cf1425d2a52832185af7cbadda09c60b0fe19fc457a92b490e32f05d57ca62544164f6066cb607b819010629fcd68c7645adce461592ccc72990
7
+ data.tar.gz: 4279ff2b8a4a7830f967f5b22edf9832267cbb51b571265f6c1d282b639a6d32d21c247896e69ab2ebcd89eae376c92836b37964624cbc670ccad2f1c9465e78
@@ -1,4 +1,4 @@
1
- Copyright (c) 2013 Josh Steiner
1
+ Copyright (c) 2013 Josh Steiner and thoughtbot, inc.
2
2
 
3
3
  MIT License
4
4
 
@@ -19,4 +19,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
19
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
20
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Borealis
2
2
 
3
- TODO: Write a gem description
3
+ Borealis finds the most prominent colors in an image, attempting to find colors that are distinct from one another.
4
+
5
+ It provides defaults which favor speed, but the defaults are easily changed if you prefer accuracy. For most purposes, the default settings should be accurate enough.
4
6
 
5
7
  ## Installation
6
8
 
@@ -18,7 +20,82 @@ Or install it yourself as:
18
20
 
19
21
  ## Usage
20
22
 
21
- TODO: Write usage instructions here
23
+ Find the three prominent colors in an image:
24
+
25
+ ```ruby
26
+ Borealis.new('image/path.jpg').colors # Returns 3 colors with hex and rgb attributes
27
+ Borealis.new('image/path.jpg').hexes # Returns 3 hex values
28
+ Borealis.new('image/path.jpg').rgbs # Returns 3 rgb values
29
+ ```
30
+
31
+ Easily get color values out of a color:
32
+
33
+ ```ruby
34
+ color = Borealis.new(file).colors.first
35
+ color.rgb # "(222, 2, 15)"
36
+ color.hex # "#DE020F"
37
+ ```
38
+
39
+ Measure distance between colors:
40
+
41
+ ```ruby
42
+ orange.rgb_distance_to red #=> 127.0
43
+ orange.lab_distance_to red #=> 39.79252198414681
44
+
45
+ maroon.rgb_distance_to dark_red #=> 11.0
46
+ maroon.lab_distance_to dark_read #=> 5.071593528474779
47
+ ```
48
+
49
+ Calculate CIE-L\*a\*b\* value of an sRGB color:
50
+
51
+ ```ruby
52
+ cyan = Borealis::Color.new(0, 255, 255)
53
+ cyan.to_lab #=> [91.11652110946342, -48.079618466228716, -14.138127754846131]
54
+ ```
55
+
56
+ Change the defaults:
57
+
58
+ ```ruby
59
+ borealis = Borealis.new('image/path.jpg',
60
+ size: '150x150',
61
+ colors: 3,
62
+ delta: 0.001,
63
+ static: false
64
+ )
65
+ ```
66
+
67
+ ### Size
68
+
69
+ _Default: '50x50'_
70
+
71
+ Size takes any [Image Geometry](http://www.imagemagick.org/script/command-line-processing.php#geometry) that imagemagick handles.
72
+
73
+ For more accurate results, use a larger image. However, this comes at a severe time cost.
74
+
75
+ ### Colors
76
+
77
+ _Default: 3_
78
+
79
+ The number of colors you want returned.
80
+
81
+ ### Iterations
82
+
83
+ _Default: 3_
84
+
85
+ ### Static
86
+
87
+ _Default: true_
88
+
89
+ Static determines whether the color output will be the same each time given the same image. Use false if you want the colors to change each run.
90
+
91
+ ## How does it work?
92
+
93
+ Borealis uses the [k-means](http://en.wikipedia.org/wiki/K-means_clustering) clustering algorithm, which in this case:
94
+
95
+ 1. Takes _n_ colors from the image as cluster centers
96
+ 2. Adds the rest of the colors to the cluster which they are closest to
97
+ 3. Finds the average color in each cluster, setting the results as new cluster centers
98
+ 4. Empties each cluster, except for the new center, and repeats steps 2-3 until convergance has been reached
22
99
 
23
100
  ## Contributing
24
101
 
@@ -27,3 +104,7 @@ TODO: Write usage instructions here
27
104
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
105
  4. Push to the branch (`git push origin my-new-feature`)
29
106
  5. Create new Pull Request
107
+
108
+ ## License
109
+
110
+ Borealis is copyright 2013 Josh Steiner and thoughtbot, inc., and may be redistributed under the terms specified in the LICENSE file.
@@ -8,15 +8,18 @@ Gem::Specification.new do |gem|
8
8
  gem.version = Borealis::VERSION
9
9
  gem.authors = ["Josh Steiner"]
10
10
  gem.email = ["josh@jsteiner.me"]
11
- gem.description = %q{Finds top colors in a given image.}
12
- gem.summary = %q{Finds top colors in a given image.}
11
+ gem.description = %q{Finds most prominent colors in a given image.}
12
+ gem.summary = %q{Finds most prominent colors in a given image.}
13
13
  gem.homepage = ""
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
16
16
  gem.test_files = gem.files.grep("spec")
17
17
  gem.require_paths = ["lib"]
18
18
 
19
+ gem.requirements << 'ImageMagick'
20
+
19
21
  gem.add_development_dependency 'rspec'
22
+ gem.add_development_dependency 'bourne'
20
23
 
21
24
  gem.add_dependency 'cocaine'
22
25
  end
@@ -1,27 +1,33 @@
1
- require "cocaine"
2
- require "borealis/color"
3
- require "borealis/image_analyzer"
4
- require "borealis/version"
1
+ require 'borealis/cluster'
2
+ require 'borealis/color'
3
+ require 'borealis/image_converter'
4
+ require 'borealis/kmeans'
5
+ require 'borealis/version'
5
6
 
6
7
  class Borealis
7
8
  attr_reader :colors
8
9
 
9
- def initialize(file, analyzer = ImageAnalyzer)
10
- analysis = analyzer.new(file).process
11
- @colors = analysis.split("\n").map { |line| line_to_color(line) }
12
- colors.sort!
10
+ def initialize(file, options = {})
11
+ image_colors = ImageConverter.new(file, options[:size]).to_colors
12
+ clusters = KMeans.new(image_colors, parse_options(options)).run
13
+ @colors = clusters.map(&:center)
13
14
  end
14
15
 
15
16
  def hexes
16
- colors.map(&:hex)
17
+ @colors.map(&:hex)
18
+ end
19
+
20
+ def rgbs
21
+ @colors.map(&:rgb)
17
22
  end
18
23
 
19
24
  private
20
25
 
21
- def line_to_color(line)
22
- line = line.scan(/\(([\s+\d+,]+)\).+([\#][0-9,A-F,a-f]{6})/).flatten
23
- rgb = line.first.split(',').map { |value| value.to_i }
24
- hex = line.last
25
- Color.new(rgb, hex)
26
+ def parse_options(options)
27
+ {
28
+ number_of_clusters: options[:colors],
29
+ delta: options[:delta],
30
+ static: options[:static]
31
+ }.reject{ |_,v| v.nil? }
26
32
  end
27
33
  end
@@ -0,0 +1,31 @@
1
+ class Borealis
2
+ class Cluster
3
+ attr_reader :center, :colors
4
+
5
+ def initialize(center)
6
+ @center = center
7
+ @colors = []
8
+ end
9
+
10
+ def recenter!
11
+ red_sum = green_sum = blue_sum = 0
12
+
13
+ colors.each do |color|
14
+ red_sum += color.red
15
+ green_sum += color.green
16
+ blue_sum += color.blue
17
+ end
18
+
19
+ old_center = @center
20
+ @center = Color.new(
21
+ red_sum / colors.length,
22
+ green_sum / colors.length,
23
+ blue_sum / colors.length
24
+ )
25
+
26
+ @colors.clear
27
+
28
+ old_center.rgb_distance_to @center
29
+ end
30
+ end
31
+ end
@@ -1,18 +1,86 @@
1
1
  class Borealis
2
2
  class Color
3
- attr_reader :rgb, :hex
3
+ include Math
4
4
 
5
- def initialize(rgb, hex)
6
- @rgb = rgb
7
- @hex = hex
5
+ attr_reader :red, :green, :blue
6
+
7
+ def initialize(red, green, blue)
8
+ @red = red
9
+ @green = green
10
+ @blue = blue
11
+ end
12
+
13
+ def rgb_distance_to(other)
14
+ Math.sqrt((red - other.red) ** 2 + (green - other.green) ** 2 + (blue - other.blue) ** 2)
15
+ end
16
+
17
+ def lab_distance_to(other)
18
+ l, a, b = to_lab
19
+ other_l, other_a, other_b = other.to_lab
20
+ Math.sqrt((l - other_l) ** 2 + (a - other_a) ** 2 + (b - other_b) ** 2)
21
+ end
22
+
23
+ def rgb
24
+ "(#{red}, #{green}, #{blue})"
25
+ end
26
+
27
+ def hex
28
+ "##{hex_segment red}#{hex_segment green}#{hex_segment blue}"
29
+ end
30
+
31
+ def ==(other)
32
+ red == other.red && green == other.green && blue == other.blue
33
+ end
34
+
35
+ # http://www.easyrgb.com/index.php?X=MATH&H=07#text7
36
+ def to_lab
37
+ reference_white_X = 95.047
38
+ reference_white_Y = 100.000
39
+ reference_white_Z = 108.883
40
+
41
+ x, y, z = to_xyz
42
+ x = x / reference_white_X
43
+ y = y / reference_white_Y
44
+ z = z / reference_white_Z
45
+
46
+ x, y, z = [x, y, z].map do |value|
47
+ if value > 0.008856
48
+ value ** (1.0 / 3.0)
49
+ else
50
+ 7.787 * value + 16.0 / 116.0
51
+ end
52
+ end
53
+
54
+ cie_L = 116 * y - 16
55
+ cie_a = 500 * (x - y)
56
+ cie_b = 200 * (y - z)
57
+
58
+ [cie_L, cie_a, cie_b]
8
59
  end
9
60
 
10
- def distance
11
- @distance ||= Math.sqrt(rgb[0] ^ 2 + rgb[1] ^ 2 + rgb[2] ^ 2)
61
+ private
62
+
63
+ def hex_segment(primary_color)
64
+ primary_color.to_s(16).rjust(2, '0').upcase
12
65
  end
13
66
 
14
- def <=>(other)
15
- distance <=> other.distance
67
+ # http://www.easyrgb.com/index.php?X=MATH&H=02#text2
68
+ def to_xyz
69
+ r, g, b = [@red, @green, @blue].map do |value|
70
+ value = value / 255.0
71
+ if value > 0.04045
72
+ value = ((value + 0.055) / 1.055) ** 2.4
73
+ else
74
+ value = value / 12.92
75
+ end
76
+ value * 100.0
77
+ end
78
+
79
+ x = r * 0.4124 + g * 0.3576 + b * 0.1805
80
+ y = r * 0.2126 + g * 0.7152 + b * 0.0722
81
+ z = r * 0.0193 + g * 0.1192 + b * 0.9505
82
+
83
+ [x, y, z]
16
84
  end
17
85
  end
18
86
  end
@@ -0,0 +1,33 @@
1
+ require 'cocaine'
2
+
3
+ class Borealis
4
+ class ImageConverter
5
+ def initialize(image, size)
6
+ @image = image
7
+ @size = size || '50x50'
8
+ end
9
+
10
+ def read_image
11
+ Cocaine::CommandLine.new(
12
+ 'convert',
13
+ "#{@image} -resize #{@size} txt:-"
14
+ ).run
15
+ end
16
+
17
+ def to_colors
18
+ colors_for(read_image)
19
+ end
20
+
21
+ private
22
+
23
+ def colors_for(data)
24
+ lines = data.split("\n").drop(1)
25
+ lines.map do |line|
26
+ line = line.scan(/\(([\d+\s+,]+)\)/).flatten
27
+ rgb_values = line.first.split(',').map { |value| value.to_i }
28
+
29
+ Color.new(*rgb_values)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,53 @@
1
+ class Borealis
2
+ class KMeans
3
+ def initialize(colors, options = {})
4
+ @colors = colors
5
+ @number_of_clusters = options[:number_of_clusters] || 3
6
+ @delta = options[:delta] || 0.01
7
+ @static = options.has_key?(:static) ? options[:static] : true
8
+
9
+ if @number_of_clusters > @colors.length
10
+ raise 'You may not have more clusters than colors.'
11
+ end
12
+ end
13
+
14
+ def run
15
+ if @colors.length == @number_of_clusters
16
+ @colors.map { |color| Cluster.new(color) }
17
+ else
18
+ max_delta = 0
19
+ while max_delta <= @delta do
20
+ @colors.each { |color| add_to_closest_cluster(color) }
21
+ max_delta = clusters.map { |cluster| cluster.recenter! }.max
22
+ end
23
+
24
+ clusters
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def clusters
31
+ @clusters ||= @number_of_clusters.times.map do |index|
32
+ if @static
33
+ # Find spaced out colors that are always the same
34
+ color_index = @colors.length * index / @number_of_clusters
35
+ color = @colors[color_index]
36
+ else
37
+ color = @colors.sample
38
+ @colors.delete color
39
+ end
40
+
41
+ Cluster.new(color)
42
+ end
43
+ end
44
+
45
+ def add_to_closest_cluster(color)
46
+ closest_cluster = clusters.min do |a, b|
47
+ color.rgb_distance_to(a.center) <=> color.rgb_distance_to(b.center)
48
+ end
49
+
50
+ closest_cluster.colors << color
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,3 @@
1
1
  class Borealis
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -1,29 +1,10 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Borealis, '#colors' do
4
- it 'returns the colors from smallest to largest distance' do
5
- image = 'spec/fixtures/winter.jpg'
6
- histogram = Borealis.new(image)
7
- expect(histogram.colors).to eq histogram.colors.sort
8
- end
9
- end
10
-
11
- describe Borealis, '#hexes' do
12
- it 'returns the correct hexes for the data provided' do
13
- image = 'spec/fixtures/winter.jpg'
14
- histogram = Borealis.new(image, FakeAnalyzer)
15
- expect(histogram.hexes).to eq %w(#2A5E9F #2C2D48)
16
- end
17
- end
18
-
19
- class FakeAnalyzer
20
- def initialize(file)
21
- end
4
+ it 'returns the number of colors requested' do
5
+ image = 'spec/fixtures/aurora_borealis.jpg'
6
+ borealis = Borealis.new(image, colors: 6)
22
7
 
23
- def process
24
- <<-eos
25
- 51076: ( 1, 2,3) #2A5E9F srgb(1,2,3)
26
- 47529: ( 4, 5, 6) #2C2D48 srgb(4,5,6)
27
- eos
8
+ expect(borealis.colors.length).to eq 6
28
9
  end
29
10
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Borealis::Cluster, '#recenter!' do
4
+ it 'returns the distance to the old center' do
5
+ center = Borealis::Color.new(1, 2, 3)
6
+ cluster = Borealis::Cluster.new(center)
7
+ cluster.colors << Borealis::Color.new(2, 4, 6)
8
+ cluster.colors << Borealis::Color.new(4, 6, 8)
9
+
10
+ cluster.recenter!
11
+
12
+ expect(cluster.center).to eq Borealis::Color.new(3, 5, 7)
13
+ end
14
+
15
+ it 'creates a new color in the center of existing colors' do
16
+ center = stub('center', :rgb_distance_to)
17
+ cluster = Borealis::Cluster.new(center)
18
+ cluster.colors << Borealis::Color.new(2, 4, 6)
19
+ cluster.colors << Borealis::Color.new(4, 6, 8)
20
+
21
+ cluster.recenter!
22
+
23
+ expect(cluster.center).to eq Borealis::Color.new(3, 5, 7)
24
+ end
25
+
26
+ it 'empties its colors' do
27
+ center = stub('center', :rgb_distance_to)
28
+ cluster = Borealis::Cluster.new(center)
29
+ cluster.colors << Borealis::Color.new(1, 2, 3)
30
+
31
+ cluster.recenter!
32
+
33
+ expect(cluster.colors).to be_empty
34
+ end
35
+ end
@@ -1,20 +1,48 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Borealis::Color, '#distance' do
4
- it 'calculates the distance correctly' do
5
- color = Borealis::Color.new([1, 2, 3], 'hex')
6
- expect(color.distance).to eq Math.sqrt(1 ^ 2 + 2 ^ 2 + 3 ^ 2)
3
+ describe Borealis::Color, '#distance_to' do
4
+ it 'calculates the RGB distance correctly' do
5
+ color = Borealis::Color.new(1, 2, 3)
6
+ other_color = Borealis::Color.new(2, 3, 4)
7
+ distance = Math.sqrt((1 - 2) ** 2 + (2 - 3) ** 2 + (3 - 4) ** 2)
8
+
9
+ expect(color.rgb_distance_to(other_color)).to eq distance
10
+ end
11
+ end
12
+
13
+ describe Borealis::Color, '#rgb' do
14
+ it 'returns a string with the correct rgb value' do
15
+ color = Borealis::Color.new(1, 2, 3)
16
+ expect(color.rgb).to eq '(1, 2, 3)'
7
17
  end
8
18
  end
9
19
 
10
- describe Borealis::Color, 'comparison' do
11
- it 'compares colors according to distance' do
12
- large_color = Borealis::Color.new([4, 5, 6], 'arbitrary')
13
- small_color = Borealis::Color.new([2, 3, 4], 'arbitrary')
14
- smallest_color = Borealis::Color.new([1, 2, 3], 'arbitrary')
20
+ describe Borealis::Color, '#hex' do
21
+ it 'returns a string with the correct hex value' do
22
+ color = Borealis::Color.new(222, 2, 15)
23
+ expect(color.hex).to eq '#DE020F'
24
+ end
25
+ end
26
+
27
+ describe Borealis::Color, 'equality' do
28
+ it 'returns true if the colors have the same rgb' do
29
+ color = Borealis::Color.new(1, 2, 3)
30
+ expect(color).to eq Borealis::Color.new(1, 2, 3)
31
+ end
32
+
33
+ it 'returns false if the colors have different rgbs' do
34
+ color = Borealis::Color.new(1, 2, 3)
35
+ expect(color).not_to eq Borealis::Color.new(2, 2, 3)
36
+ end
37
+ end
15
38
 
16
- colors = [smallest_color, large_color, small_color]
39
+ describe Borealis::Color, '#to_lab' do
40
+ it 'converts rgb to lab correctly' do
41
+ color = Borealis::Color.new(255, 204, 0)
17
42
 
18
- expect(colors.sort).to eq [smallest_color, small_color, large_color]
43
+ # http://www.easyrgb.com/index.php?X=CALC#Result
44
+ expect(color.to_lab[0]).to be_within(0.01).of(84.197)
45
+ expect(color.to_lab[1]).to be_within(0.01).of(3.680)
46
+ expect(color.to_lab[2]).to be_within(0.01).of(85.223)
19
47
  end
20
48
  end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe Borealis::ImageConverter, '#to_colors' do
4
+ it 'returns as many colors as there are pixels' do
5
+ image = 'spec/fixtures/aurora_borealis.jpg'
6
+ colors = Borealis::ImageConverter.new(image, '10x10!').to_colors
7
+
8
+ expect(colors.length).to eq 100
9
+ end
10
+ end
11
+
12
+ describe Borealis::ImageConverter, '#read_image' do
13
+ it 'returns colors in the correct format' do
14
+ image = 'spec/fixtures/aurora_borealis.jpg'
15
+ image_data = Borealis::ImageConverter.new(image, '10x10').read_image
16
+
17
+ expect(image_data).to match(/\(([\s+\d+,]+)\).+([\#][0-9,A-F,a-f]{6}).+(rgb)/)
18
+ end
19
+
20
+ it 'raises Cocaine::ExitStatusError when the image is not present' do
21
+ image = 'nonexistent.jpg'
22
+ image_converter = Borealis::ImageConverter.new(image, 'dimensions')
23
+
24
+ silence_stderr do
25
+ expect { image_converter.read_image }.to raise_error(Cocaine::ExitStatusError)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Borealis::KMeans do
4
+ it 'raises if there are more clusters than colors' do
5
+ colors = []
6
+ 3.times { colors << Borealis::Color.new(1, 2, 3) }
7
+
8
+ expect do
9
+ Borealis::KMeans.new(colors, number_of_clusters: 4)
10
+ end.to raise_error 'You may not have more clusters than colors.'
11
+ end
12
+ end
13
+
14
+ describe Borealis::KMeans, '#run' do
15
+ it 'sets the colors as cluster centers if there are as many colors as clusters' do
16
+ colors = []
17
+ 3.times { colors << stub('color') }
18
+
19
+ clusters = Borealis::KMeans.new(colors, number_of_clusters: 3).run
20
+
21
+ expect(clusters.map(&:center)).to eq colors
22
+ end
23
+
24
+ it 'returns number_of_clusters clusters' do
25
+ colors = []
26
+ 20.times { |index| colors << Borealis::Color.new(index, index * 2, index * 3) }
27
+
28
+ clusters = Borealis::KMeans.new(colors, number_of_clusters: 8).run
29
+
30
+ expect(clusters.length).to eq 8
31
+ end
32
+ end
@@ -1,7 +1,10 @@
1
1
  require 'borealis'
2
2
 
3
+ require 'bourne'
4
+
3
5
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |file| require file }
4
6
 
5
7
  RSpec.configure do |config|
6
8
  config.order = 'random'
9
+ config.mock_with :mocha
7
10
  end
metadata CHANGED
@@ -1,49 +1,58 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: borealis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 0.0.2
6
5
  platform: ruby
7
6
  authors:
8
7
  - Josh Steiner
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-02-09 00:00:00.000000000 Z
11
+ date: 2013-10-11 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rspec
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bourne
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
28
39
  - !ruby/object:Gem::Version
29
40
  version: '0'
30
41
  - !ruby/object:Gem::Dependency
31
42
  name: cocaine
32
43
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
44
  requirements:
35
- - - ! '>='
45
+ - - '>='
36
46
  - !ruby/object:Gem::Version
37
47
  version: '0'
38
48
  type: :runtime
39
49
  prerelease: false
40
50
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
51
  requirements:
43
- - - ! '>='
52
+ - - '>='
44
53
  - !ruby/object:Gem::Version
45
54
  version: '0'
46
- description: Finds top colors in a given image.
55
+ description: Finds most prominent colors in a given image.
47
56
  email:
48
57
  - josh@jsteiner.me
49
58
  executables: []
@@ -56,40 +65,48 @@ files:
56
65
  - LICENSE.txt
57
66
  - README.md
58
67
  - Rakefile
68
+ - bin/stubs/autospec
69
+ - bin/stubs/htmldiff
70
+ - bin/stubs/ldiff
71
+ - bin/stubs/rspec
59
72
  - borealis.gemspec
60
73
  - lib/borealis.rb
74
+ - lib/borealis/cluster.rb
61
75
  - lib/borealis/color.rb
62
- - lib/borealis/image_analyzer.rb
76
+ - lib/borealis/image_converter.rb
77
+ - lib/borealis/kmeans.rb
63
78
  - lib/borealis/version.rb
64
79
  - spec/borealis/borealis_spec.rb
80
+ - spec/borealis/cluster_spec.rb
65
81
  - spec/borealis/color_spec.rb
66
- - spec/borealis/image_analyzer_spec.rb
82
+ - spec/borealis/image_converter_spec.rb
83
+ - spec/borealis/kmeans_spec.rb
67
84
  - spec/borealis/version_spec.rb
68
- - spec/fixtures/winter.jpg
85
+ - spec/fixtures/aurora_borealis.jpg
69
86
  - spec/spec_helper.rb
70
87
  - spec/support/silence_stderr.rb
71
88
  homepage: ''
72
89
  licenses: []
90
+ metadata: {}
73
91
  post_install_message:
74
92
  rdoc_options: []
75
93
  require_paths:
76
94
  - lib
77
95
  required_ruby_version: !ruby/object:Gem::Requirement
78
- none: false
79
96
  requirements:
80
- - - ! '>='
97
+ - - '>='
81
98
  - !ruby/object:Gem::Version
82
99
  version: '0'
83
100
  required_rubygems_version: !ruby/object:Gem::Requirement
84
- none: false
85
101
  requirements:
86
- - - ! '>='
102
+ - - '>='
87
103
  - !ruby/object:Gem::Version
88
104
  version: '0'
89
- requirements: []
105
+ requirements:
106
+ - ImageMagick
90
107
  rubyforge_project:
91
- rubygems_version: 1.8.23
108
+ rubygems_version: 2.0.3
92
109
  signing_key:
93
- specification_version: 3
94
- summary: Finds top colors in a given image.
110
+ specification_version: 4
111
+ summary: Finds most prominent colors in a given image.
95
112
  test_files: []
@@ -1,22 +0,0 @@
1
- class Borealis
2
- class ImageAnalyzer
3
- def initialize(image)
4
- @image = image
5
- end
6
-
7
- def process
8
- line = Cocaine::CommandLine.new(histogram_command)
9
- line.run.strip
10
- end
11
-
12
- private
13
-
14
- def histogram_command
15
- quantize = "convert #{@image} +dither -colors 10 gif:-"
16
- histogramize = "convert gif:- -define histogram:unique-colors=true \
17
- -format %c histogram:info:-"
18
-
19
- "#{quantize} | #{histogramize}"
20
- end
21
- end
22
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Borealis::ImageAnalyzer, '#process' do
4
- it 'returns data in the correct format' do
5
- image = 'spec/fixtures/winter.jpg'
6
- analysis = Borealis::ImageAnalyzer.new(image).process
7
-
8
- expect(analysis).to match(/\(([\s+\d+,]+)\).+([\#][0-9,A-F,a-f]{6})/)
9
- end
10
-
11
- it 'returns 10 lines' do
12
- image = 'spec/fixtures/winter.jpg'
13
- analysis = Borealis::ImageAnalyzer.new(image).process
14
-
15
- expect(analysis.lines.count).to eq 10
16
- end
17
-
18
- it 'raises Cocaine::ExitStatusError when the image is not present' do
19
- image = 'spec/fixtures/nonexistent.jpg'
20
-
21
- silence_stderr do
22
- expect {
23
- Borealis::ImageAnalyzer.new(image).process
24
- }.to raise_error(Cocaine::ExitStatusError)
25
- end
26
- end
27
- end
Binary file