recolor 0.1.1
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.
- checksums.yaml +7 -0
- data/lib/recolor.rb +70 -0
- data/lib/recolor/color.rb +11 -0
- data/lib/recolor/converter.rb +53 -0
- data/lib/recolor/models.rb +20 -0
- data/lib/recolor/models/hex.rb +21 -0
- data/lib/recolor/models/hpluv.rb +33 -0
- data/lib/recolor/models/hsluv.rb +51 -0
- data/lib/recolor/models/lch.rb +44 -0
- data/lib/recolor/models/luv.rb +35 -0
- data/lib/recolor/models/rgb.rb +38 -0
- data/lib/recolor/models/xyz.rb +45 -0
- data/lib/recolor/version.rb +3 -0
- metadata +55 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 0f36003993048fe3779cebfe5a674e7937e9d007
|
|
4
|
+
data.tar.gz: e9b3747ba265f90aa021973729071aa218c4e475
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: de88f6cc4fa94eab41a2f2bf3cc1a0f746993a5a314a729cf4315efbef415fa309ee1ee150cd2cf168b2d3b38b73d7af4de4e5b599277588974baf1f7c8bba4e
|
|
7
|
+
data.tar.gz: 3a708f24e8a041cfd1d83aaa013106fe532bd1d234927e1d72fa48a0ba055294a70d33be56967c517966710d557bbc0a317ca35957d20d00c61ba03afb15cc86
|
data/lib/recolor.rb
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
require "recolor/version"
|
|
2
|
+
|
|
3
|
+
module Recolor
|
|
4
|
+
require "recolor/color"
|
|
5
|
+
require "recolor/models"
|
|
6
|
+
require "recolor/models/hex"
|
|
7
|
+
require "recolor/models/hsluv"
|
|
8
|
+
require "recolor/models/hpluv"
|
|
9
|
+
require "recolor/models/lch"
|
|
10
|
+
require "recolor/models/luv"
|
|
11
|
+
require "recolor/models/rgb"
|
|
12
|
+
require "recolor/models/xyz"
|
|
13
|
+
require "recolor/converter"
|
|
14
|
+
|
|
15
|
+
class Recolor
|
|
16
|
+
attr_accessor :converter
|
|
17
|
+
attr_accessor :models
|
|
18
|
+
|
|
19
|
+
def initialize
|
|
20
|
+
@models = {}
|
|
21
|
+
@models[:hex] = Models::Hex.new
|
|
22
|
+
@models[:hpluv] = Models::HPLuv.new
|
|
23
|
+
@models[:hsluv] = Models::HSLuv.new
|
|
24
|
+
@models[:lch] = Models::LCh.new
|
|
25
|
+
@models[:luv] = Models::Luv.new
|
|
26
|
+
@models[:rgb] = Models::RGB.new
|
|
27
|
+
@models[:xyz] = Models::XYZ.new
|
|
28
|
+
@converter = Converter.new
|
|
29
|
+
@converter.models[:hex] = @models[:hex]
|
|
30
|
+
@converter.models[:hpluv] = @models[:hpluv]
|
|
31
|
+
@converter.models[:hsluv] = @models[:hsluv]
|
|
32
|
+
@converter.models[:lch] = @models[:lch]
|
|
33
|
+
@converter.models[:luv] = @models[:luv]
|
|
34
|
+
@converter.models[:rgb] = @models[:rgb]
|
|
35
|
+
@converter.models[:xyz] = @models[:xyz]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def color(model, tuple)
|
|
39
|
+
@color = Color.new(model, tuple)
|
|
40
|
+
|
|
41
|
+
return self.clone
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to(model)
|
|
45
|
+
raise Exception.new("Color definition not found.") unless @color
|
|
46
|
+
|
|
47
|
+
source = @color.model
|
|
48
|
+
tuple = @color.tuple
|
|
49
|
+
tuple = @converter.convert(tuple, source, model)
|
|
50
|
+
|
|
51
|
+
return color(model, tuple)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def model
|
|
55
|
+
return @color.model
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def tuple
|
|
59
|
+
return @color.tuple
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def format
|
|
63
|
+
yield @color.tuple
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def to_s
|
|
67
|
+
return @models[model].print(tuple)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
class Converter
|
|
3
|
+
attr_accessor :models
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@models = {}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def convert(tuple, source, destination)
|
|
10
|
+
return tuple unless source != destination
|
|
11
|
+
|
|
12
|
+
raise ArgumentError.new("No #{source} model found.") unless @models.include?(source)
|
|
13
|
+
|
|
14
|
+
@steps = []
|
|
15
|
+
resolve(source, destination, @models)
|
|
16
|
+
|
|
17
|
+
raise ArgumentError.new("Unable to convert from #{source} to #{destination}.") if @steps.empty?
|
|
18
|
+
|
|
19
|
+
model = @models[source]
|
|
20
|
+
|
|
21
|
+
@steps.each do |step|
|
|
22
|
+
tuple = model.send(step, tuple)
|
|
23
|
+
model = @models[step]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
return tuple
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def resolve(source, destination, models)
|
|
32
|
+
model = models[source]
|
|
33
|
+
models = models.reject { |name| name == source }
|
|
34
|
+
|
|
35
|
+
models.keys.each do |name|
|
|
36
|
+
if model.respond_to?(destination)
|
|
37
|
+
@steps << destination
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if @steps.include?(destination)
|
|
41
|
+
break
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if model.respond_to?(name)
|
|
45
|
+
@steps << name
|
|
46
|
+
resolve(name, destination, models)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
@steps = @steps.reject { |name| name == source } unless @steps.include?(destination)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class Model
|
|
4
|
+
attr_accessor :format
|
|
5
|
+
|
|
6
|
+
KAPPA = 903.2962962962963
|
|
7
|
+
EPSILON = 0.0088564516790356308
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@format = lambda do |tuple|
|
|
11
|
+
return tuple
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def print(tuple)
|
|
16
|
+
return "#{@format.call(tuple)}"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class Hex < Model
|
|
4
|
+
def rgb(tuple)
|
|
5
|
+
hex = [
|
|
6
|
+
tuple[0],
|
|
7
|
+
tuple[1],
|
|
8
|
+
tuple[2]
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
rgb = hex.map do |v|
|
|
12
|
+
v = v + v if v.length == 1
|
|
13
|
+
v = v.hex
|
|
14
|
+
v = v / 255
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
return rgb
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class HPLuv < Model
|
|
4
|
+
def lch(tuple)
|
|
5
|
+
h = tuple[0]
|
|
6
|
+
s = tuple[1]
|
|
7
|
+
l = tuple[2]
|
|
8
|
+
|
|
9
|
+
return [100, 0.0, h] if l > 99.9999999
|
|
10
|
+
return [0.0, 0.0, h] if l < 0.00000001
|
|
11
|
+
|
|
12
|
+
chroma = HPLuv.chroma(l)
|
|
13
|
+
c = chroma / 100.0 * s
|
|
14
|
+
|
|
15
|
+
return [l, c, h]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def HPLuv.chroma(l)
|
|
19
|
+
lengths = []
|
|
20
|
+
|
|
21
|
+
HSLuv.bounds(l).each do |line|
|
|
22
|
+
m = line[0]
|
|
23
|
+
b = line[1]
|
|
24
|
+
x = (b - 0.0) / ((-1.0 / m) - m)
|
|
25
|
+
length = Math.sqrt(x**2 + (b + x * m)**2)
|
|
26
|
+
lengths << length
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
return lengths.min
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class HSLuv < Model
|
|
4
|
+
def lch(tuple)
|
|
5
|
+
h = tuple[0]
|
|
6
|
+
s = tuple[1]
|
|
7
|
+
l = tuple[2]
|
|
8
|
+
|
|
9
|
+
return [100, 0.0, h] if l > 99.9999999
|
|
10
|
+
return [0.0, 0.0, h] if l < 0.00000001
|
|
11
|
+
|
|
12
|
+
chroma = HSLuv.chroma(l, h)
|
|
13
|
+
c = chroma / 100.0 * s
|
|
14
|
+
|
|
15
|
+
return [l, c, h]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def HSLuv.bounds(l)
|
|
19
|
+
s = ((l + 16)**3) / 1560896.0
|
|
20
|
+
s = s > EPSILON ? s : l / KAPPA
|
|
21
|
+
matrix = RGB::MATRIX.to_a
|
|
22
|
+
lines = []
|
|
23
|
+
|
|
24
|
+
matrix.each do |m1, m2, m3|
|
|
25
|
+
[0, 1].each do |d|
|
|
26
|
+
bottom = (632260 * m3 - 126452 * m2) * s + 126452 * d
|
|
27
|
+
m = ((284517 * m1 - 94839 * m3) * s) / bottom
|
|
28
|
+
b = ((838422 * m3 + 769860 * m2 + 731718 * m1) * l * s - 769860 * d * l) / bottom
|
|
29
|
+
lines << [m, b]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
return lines
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def HSLuv.chroma(l, h)
|
|
37
|
+
angle = h / 360.0 * Math::PI * 2.0
|
|
38
|
+
lengths = []
|
|
39
|
+
|
|
40
|
+
HSLuv.bounds(l).each do |line|
|
|
41
|
+
m = line[0]
|
|
42
|
+
b = line[1]
|
|
43
|
+
length = b / (Math.sin(angle) - m * Math.cos(angle))
|
|
44
|
+
lengths << length if length > 0
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
return lengths.min
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class LCh < Model
|
|
4
|
+
def luv(tuple)
|
|
5
|
+
l = tuple[0]
|
|
6
|
+
c = tuple[1]
|
|
7
|
+
h = tuple[2]
|
|
8
|
+
h = h * Math::PI / 180.0
|
|
9
|
+
u = Math::cos(h) * c
|
|
10
|
+
v = Math::sin(h) * c
|
|
11
|
+
|
|
12
|
+
return [l, u, v]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def hpluv(tuple)
|
|
16
|
+
l = tuple[0]
|
|
17
|
+
c = tuple[1]
|
|
18
|
+
h = tuple[2]
|
|
19
|
+
|
|
20
|
+
return [h, 0.0, 100] if l > 99.9999999
|
|
21
|
+
return [h, 0.0, 0.0] if l < 0.00000001
|
|
22
|
+
|
|
23
|
+
chroma = HPLuv.chroma(l)
|
|
24
|
+
p = c / chroma * 100.0
|
|
25
|
+
|
|
26
|
+
return [h, p, l]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def hsluv(tuple)
|
|
30
|
+
l = tuple[0]
|
|
31
|
+
c = tuple[1]
|
|
32
|
+
h = tuple[2]
|
|
33
|
+
|
|
34
|
+
return [h, 0.0, 100] if l > 99.9999999
|
|
35
|
+
return [h, 0.0, 0.0] if l < 0.00000001
|
|
36
|
+
|
|
37
|
+
chroma = HSLuv.chroma(l, h)
|
|
38
|
+
s = c / chroma * 100.8
|
|
39
|
+
|
|
40
|
+
return [h, s, l]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class Luv < Model
|
|
4
|
+
REFERENCE_U = 0.19783000664283
|
|
5
|
+
REFERENCE_V = 0.46831999493879
|
|
6
|
+
|
|
7
|
+
def xyz(tuple)
|
|
8
|
+
l = tuple[0]
|
|
9
|
+
u = tuple[1]
|
|
10
|
+
v = tuple[2]
|
|
11
|
+
|
|
12
|
+
return [0.0, 0.0, 0.0] if l == 0.0
|
|
13
|
+
|
|
14
|
+
y = l > 8 ? XYZ::REFERENCE_Y * ((l + 16.0) / 116.0)**3.0 : XYZ::REFERENCE_Y * l / KAPPA
|
|
15
|
+
u = u / (13.0 * l) + REFERENCE_U
|
|
16
|
+
v = v / (13.0 * l) + REFERENCE_V
|
|
17
|
+
x = 0.0 - (9.0 * y * u) / ((u - 4.0) * v - u * v)
|
|
18
|
+
z = (9.0 * y - (15.0 * v * y) - (v * x)) / (3.0 * v)
|
|
19
|
+
|
|
20
|
+
return [x, y, z]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def lch(tuple)
|
|
24
|
+
l = tuple[0]
|
|
25
|
+
u = tuple[1]
|
|
26
|
+
v = tuple[2]
|
|
27
|
+
c = Math.sqrt(u * u + v * v)
|
|
28
|
+
h = Math.atan2(v, u) * 180 / Math::PI
|
|
29
|
+
h = h < 0.0 ? h + 360.0 : h
|
|
30
|
+
|
|
31
|
+
return [l, c, h]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "matrix"
|
|
2
|
+
|
|
3
|
+
module Recolor
|
|
4
|
+
module Models
|
|
5
|
+
class RGB < Model
|
|
6
|
+
MATRIX = Matrix[
|
|
7
|
+
[3.240969941904521, -1.537383177570093, -0.498610760293],
|
|
8
|
+
[-0.96924363628087, 1.87596750150772, 0.041555057407175],
|
|
9
|
+
[0.055630079696993, -0.20397695888897, 1.056971514242878]
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
def hex(tuple)
|
|
13
|
+
hex = tuple.map do |v|
|
|
14
|
+
v = v * 255
|
|
15
|
+
v = v.round
|
|
16
|
+
v = v.to_s(16)
|
|
17
|
+
v = v.length == 1 ? "0" + v : v
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
return hex
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def xyz(tuple)
|
|
24
|
+
rgb = tuple.map do |v|
|
|
25
|
+
v < 0.04045 ? v / 12.92 : ((v + 0.055) / 1.055)**2.4
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
rgb = Matrix[rgb].transpose
|
|
29
|
+
xyz = XYZ::MATRIX * rgb
|
|
30
|
+
xyz = xyz.transpose
|
|
31
|
+
xyz = xyz.row(0)
|
|
32
|
+
xyz = xyz.to_a
|
|
33
|
+
|
|
34
|
+
return xyz
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
module Recolor
|
|
2
|
+
module Models
|
|
3
|
+
class XYZ < Model
|
|
4
|
+
MATRIX = Matrix[
|
|
5
|
+
[0.41239079926595, 0.35758433938387, 0.18048078840183],
|
|
6
|
+
[0.21263900587151, 0.71516867876775, 0.072192315360733],
|
|
7
|
+
[0.019330818715591, 0.11919477979462, 0.95053215224966]
|
|
8
|
+
]
|
|
9
|
+
REFERENCE_X = 0.95045592705167
|
|
10
|
+
REFERENCE_Y = 1.0
|
|
11
|
+
REFERENCE_Z = 1.089057750759878
|
|
12
|
+
|
|
13
|
+
def rgb(tuple)
|
|
14
|
+
xyz = Matrix[tuple].transpose
|
|
15
|
+
rgb = RGB::MATRIX * xyz
|
|
16
|
+
|
|
17
|
+
rgb = rgb.map do |v|
|
|
18
|
+
v <= 0.0031308 ? 12.92 * v : (1.055 * (v**(1.0 / 2.4)) - 0.055)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
rgb = rgb.transpose
|
|
22
|
+
rgb = rgb.row(0)
|
|
23
|
+
rgb = rgb.to_a
|
|
24
|
+
|
|
25
|
+
return rgb
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def luv(tuple)
|
|
29
|
+
x = tuple[0]
|
|
30
|
+
y = tuple[1]
|
|
31
|
+
z = tuple[2]
|
|
32
|
+
l = y > EPSILON ? l = 116.0 * ((y / REFERENCE_Y)**(1.0 / 3.0)) - 16.0 : l = y / REFERENCE_Y * KAPPA
|
|
33
|
+
|
|
34
|
+
return [0.0, 0.0, 0.0] if l == 0.0
|
|
35
|
+
|
|
36
|
+
u = (4.0 * x) / (x + (15.0 * y) + (3.0 * z))
|
|
37
|
+
v = (9.0 * y) / (x + (15.0 * y) + (3.0 * z))
|
|
38
|
+
u = 13.0 * l * (u - Luv::REFERENCE_U)
|
|
39
|
+
v = 13.0 * l * (v - Luv::REFERENCE_V)
|
|
40
|
+
|
|
41
|
+
return [l, u, v]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: recolor
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Alberto Beloni
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2017-10-11 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description:
|
|
14
|
+
email:
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- lib/recolor.rb
|
|
20
|
+
- lib/recolor/color.rb
|
|
21
|
+
- lib/recolor/converter.rb
|
|
22
|
+
- lib/recolor/models.rb
|
|
23
|
+
- lib/recolor/models/hex.rb
|
|
24
|
+
- lib/recolor/models/hpluv.rb
|
|
25
|
+
- lib/recolor/models/hsluv.rb
|
|
26
|
+
- lib/recolor/models/lch.rb
|
|
27
|
+
- lib/recolor/models/luv.rb
|
|
28
|
+
- lib/recolor/models/rgb.rb
|
|
29
|
+
- lib/recolor/models/xyz.rb
|
|
30
|
+
- lib/recolor/version.rb
|
|
31
|
+
homepage: https://github.com/albertobeloni/ruby-recolor
|
|
32
|
+
licenses:
|
|
33
|
+
- MIT
|
|
34
|
+
metadata: {}
|
|
35
|
+
post_install_message:
|
|
36
|
+
rdoc_options: []
|
|
37
|
+
require_paths:
|
|
38
|
+
- lib
|
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
40
|
+
requirements:
|
|
41
|
+
- - ">="
|
|
42
|
+
- !ruby/object:Gem::Version
|
|
43
|
+
version: '0'
|
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
requirements: []
|
|
50
|
+
rubyforge_project:
|
|
51
|
+
rubygems_version: 2.5.1
|
|
52
|
+
signing_key:
|
|
53
|
+
specification_version: 4
|
|
54
|
+
summary: Recolor is a Ruby gem to convert between color models.
|
|
55
|
+
test_files: []
|