colorscore 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of colorscore might be problematic. Click here for more details.
- data/lib/colorscore/histogram.rb +5 -5
- data/lib/colorscore/metrics.rb +15 -15
- data/lib/colorscore/palette.rb +9 -9
- data/lib/colorscore/version.rb +1 -1
- data/test/fixtures/transparency.png +0 -0
- data/test/histogram_test.rb +8 -6
- metadata +53 -64
data/lib/colorscore/histogram.rb
CHANGED
@@ -4,17 +4,17 @@ module Colorscore
|
|
4
4
|
output = `convert #{image_path} -resize 400x400 -format %c -dither None -quantize YIQ -colors #{colors} -depth #{depth} histogram:info:-`
|
5
5
|
@lines = output.lines.sort.reverse.map(&:strip).reject(&:empty?)
|
6
6
|
end
|
7
|
-
|
7
|
+
|
8
8
|
# Returns an array of colors in descending order of occurances.
|
9
9
|
def colors
|
10
|
-
hex_values = @lines.map { |line| line[/#[0-9A-F]
|
11
|
-
hex_values.map { |hex| Color::RGB.from_html(
|
10
|
+
hex_values = @lines.map { |line| line[/#([0-9A-F]{6}) /, 1] }.compact
|
11
|
+
hex_values.map { |hex| Color::RGB.from_html(hex) }
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def color_counts
|
15
15
|
@lines.map { |line| line.split(':')[0].to_i }
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def scores
|
19
19
|
total = color_counts.inject(:+).to_f
|
20
20
|
scores = color_counts.map { |count| count / total }
|
data/lib/colorscore/metrics.rb
CHANGED
@@ -3,19 +3,19 @@ module Colorscore
|
|
3
3
|
def self.similarity(a, b)
|
4
4
|
1 - distance(a, b)
|
5
5
|
end
|
6
|
-
|
6
|
+
|
7
7
|
def self.distance(color_1, color_2)
|
8
8
|
l1, a1, b1 = xyz_to_lab(*rgb_to_xyz(color_1))
|
9
9
|
l2, a2, b2 = xyz_to_lab(*rgb_to_xyz(color_2))
|
10
|
-
|
10
|
+
|
11
11
|
distance = delta_e_cie_2000(l1, a1, b1, l2, a2, b2)
|
12
12
|
scale(distance, 0..100)
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
# Ported from colormath for Python.
|
16
16
|
def self.delta_e_cie_2000(l1, a1, b1, l2, a2, b2)
|
17
17
|
kl = kc = kh = 1
|
18
|
-
|
18
|
+
|
19
19
|
avg_lp = (l1 + l2) / 2.0
|
20
20
|
c1 = Math.sqrt((a1 ** 2) + (b1 ** 2))
|
21
21
|
c2 = Math.sqrt((a2 ** 2) + (b2 ** 2))
|
@@ -66,27 +66,27 @@ module Colorscore
|
|
66
66
|
|
67
67
|
delta_e = Math.sqrt(((delta_lp / (s_l * kl)) ** 2) + ((delta_cp / (s_c * kc)) ** 2) + ((delta_hp / (s_h * kh)) ** 2) + r_t * (delta_cp / (s_c * kc)) * (delta_hp / (s_h * kh)))
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
def self.rgb_to_xyz(color)
|
71
71
|
color = color.to_rgb
|
72
72
|
r, g, b = color.r, color.g, color.b
|
73
|
-
|
73
|
+
|
74
74
|
# assuming sRGB (D65)
|
75
75
|
r = (r <= 0.04045) ? r/12.92 : ((r+0.055)/1.055) ** 2.4
|
76
76
|
g = (g <= 0.04045) ? g/12.92 : ((g+0.055)/1.055) ** 2.4
|
77
77
|
b = (b <= 0.04045) ? b/12.92 : ((b+0.055)/1.055) ** 2.4
|
78
|
-
|
78
|
+
|
79
79
|
r *= 100
|
80
80
|
g *= 100
|
81
81
|
b *= 100
|
82
|
-
|
82
|
+
|
83
83
|
x = 0.412453*r + 0.357580*g + 0.180423*b
|
84
84
|
y = 0.212671*r + 0.715160*g + 0.072169*b
|
85
85
|
z = 0.019334*r + 0.119193*g + 0.950227*b
|
86
|
-
|
86
|
+
|
87
87
|
[x, y, z]
|
88
88
|
end
|
89
|
-
|
89
|
+
|
90
90
|
def self.xyz_to_lab(x, y, z)
|
91
91
|
x /= 95.047
|
92
92
|
y /= 100.000
|
@@ -97,13 +97,13 @@ module Colorscore
|
|
97
97
|
else
|
98
98
|
x = (7.787 * x) + (16.0 / 116)
|
99
99
|
end
|
100
|
-
|
100
|
+
|
101
101
|
if y > 0.008856
|
102
102
|
y = y ** (1.0/3)
|
103
103
|
else
|
104
104
|
y = (7.787 * y) + (16.0 / 116)
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
if z > 0.008856
|
108
108
|
z = z ** (1.0/3)
|
109
109
|
else
|
@@ -116,7 +116,7 @@ module Colorscore
|
|
116
116
|
|
117
117
|
[l, a, b]
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
def self.scale(number, from_range, to_range=0..1, clamp=true)
|
121
121
|
if clamp && number <= from_range.begin
|
122
122
|
position = 0
|
@@ -125,10 +125,10 @@ module Colorscore
|
|
125
125
|
else
|
126
126
|
position = (number - from_range.begin).to_f / (from_range.end - from_range.begin)
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
position * (to_range.end - to_range.begin) + to_range.begin
|
130
130
|
end
|
131
|
-
|
131
|
+
|
132
132
|
def self.radians(degrees); degrees * Math::PI / 180; end
|
133
133
|
def self.degrees(radians); radians * 180 / Math::PI; end
|
134
134
|
end
|
data/lib/colorscore/palette.rb
CHANGED
@@ -5,33 +5,33 @@ module Colorscore
|
|
5
5
|
"669900", "336600", "666600", "999900", "cccc33", "ffff00",
|
6
6
|
"ffcc33", "ff9900", "ff6600", "cc6633", "996633", "663300",
|
7
7
|
"000000", "999999", "cccccc", "ffffff"]
|
8
|
-
|
8
|
+
|
9
9
|
def self.default
|
10
10
|
from_hex DEFAULT
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def self.from_hex(hex_values)
|
14
14
|
new hex_values.map { |hex| Color::RGB.from_html(hex) }
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def scores(histogram_scores, distance_threshold=0.275)
|
18
18
|
scores = map do |palette_color|
|
19
19
|
score = 0
|
20
|
-
|
20
|
+
|
21
21
|
histogram_scores.each_with_index do |item, index|
|
22
22
|
color_score, color = *item
|
23
|
-
|
23
|
+
|
24
24
|
color = color.to_hsl.tap { |c| c.s = 0.05 + c.s * (4 - c.l * 2.5) }.to_rgb
|
25
|
-
|
25
|
+
|
26
26
|
if (distance = Metrics.distance(palette_color, color)) < distance_threshold
|
27
27
|
distance_penalty = (1 - distance) ** 4
|
28
28
|
score += color_score * distance_penalty
|
29
|
-
end
|
29
|
+
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
[score, palette_color]
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
scores.reject { |score, color| score <= 0.05 }.
|
36
36
|
sort_by { |score, color| score }.
|
37
37
|
reverse
|
data/lib/colorscore/version.rb
CHANGED
Binary file
|
data/test/histogram_test.rb
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
require File.expand_path("../test_helper", __FILE__)
|
2
2
|
|
3
3
|
class HistogramTest < Test::Unit::TestCase
|
4
|
-
def setup
|
5
|
-
@colors = 7
|
6
|
-
@histogram = Histogram.new("test/fixtures/skydiver.jpg", @colors)
|
7
|
-
end
|
8
|
-
|
9
4
|
def test_color_count_is_correct
|
10
|
-
|
5
|
+
colors = 7
|
6
|
+
histogram = Histogram.new("test/fixtures/skydiver.jpg", colors)
|
7
|
+
assert_equal colors, histogram.colors.size
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_transparency_is_ignored
|
11
|
+
histogram = Histogram.new("test/fixtures/transparency.png")
|
12
|
+
assert_equal Color::RGB.from_html('0000ff'), histogram.colors.first
|
11
13
|
end
|
12
14
|
end
|
metadata
CHANGED
@@ -1,60 +1,56 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: colorscore
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 3
|
10
|
-
version: 0.0.3
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Milo Winningham
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
- !ruby/object:Gem::Dependency
|
21
|
-
prerelease: false
|
22
|
-
type: :runtime
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
-
none: false
|
25
|
-
requirements:
|
26
|
-
- - ">="
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
hash: 3
|
29
|
-
segments:
|
30
|
-
- 0
|
31
|
-
version: "0"
|
12
|
+
date: 2012-11-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
32
15
|
name: color
|
33
|
-
|
34
|
-
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
35
23
|
prerelease: false
|
36
|
-
|
37
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
25
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
|
44
|
-
- 0
|
45
|
-
version: "0"
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
46
31
|
name: rake
|
47
|
-
|
48
|
-
|
49
|
-
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Finds the dominant colors in an image and scores them against a user-defined
|
47
|
+
palette, using the CIE2000 Delta E formula.
|
48
|
+
email:
|
50
49
|
- milo@winningham.net
|
51
50
|
executables: []
|
52
|
-
|
53
51
|
extensions: []
|
54
|
-
|
55
52
|
extra_rdoc_files: []
|
56
|
-
|
57
|
-
files:
|
53
|
+
files:
|
58
54
|
- .gitignore
|
59
55
|
- Gemfile
|
60
56
|
- README.md
|
@@ -66,45 +62,38 @@ files:
|
|
66
62
|
- lib/colorscore/palette.rb
|
67
63
|
- lib/colorscore/version.rb
|
68
64
|
- test/fixtures/skydiver.jpg
|
65
|
+
- test/fixtures/transparency.png
|
69
66
|
- test/histogram_test.rb
|
70
67
|
- test/metrics_test.rb
|
71
68
|
- test/palette_test.rb
|
72
69
|
- test/test_helper.rb
|
73
70
|
homepage:
|
74
71
|
licenses: []
|
75
|
-
|
76
72
|
post_install_message:
|
77
73
|
rdoc_options: []
|
78
|
-
|
79
|
-
require_paths:
|
74
|
+
require_paths:
|
80
75
|
- lib
|
81
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
77
|
none: false
|
83
|
-
requirements:
|
84
|
-
- -
|
85
|
-
- !ruby/object:Gem::Version
|
86
|
-
|
87
|
-
|
88
|
-
- 0
|
89
|
-
version: "0"
|
90
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
83
|
none: false
|
92
|
-
requirements:
|
93
|
-
- -
|
94
|
-
- !ruby/object:Gem::Version
|
95
|
-
|
96
|
-
segments:
|
97
|
-
- 0
|
98
|
-
version: "0"
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
99
88
|
requirements: []
|
100
|
-
|
101
89
|
rubyforge_project:
|
102
|
-
rubygems_version: 1.8.
|
90
|
+
rubygems_version: 1.8.23
|
103
91
|
signing_key:
|
104
92
|
specification_version: 3
|
105
93
|
summary: Finds the dominant colors in an image.
|
106
|
-
test_files:
|
94
|
+
test_files:
|
107
95
|
- test/fixtures/skydiver.jpg
|
96
|
+
- test/fixtures/transparency.png
|
108
97
|
- test/histogram_test.rb
|
109
98
|
- test/metrics_test.rb
|
110
99
|
- test/palette_test.rb
|