color-tools 1.2.0 → 1.3.0
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.
- data/Changelog +35 -1
- data/Install +11 -2
- data/README +44 -12
- data/Rakefile +11 -2
- data/lib/color.rb +35 -158
- data/lib/color/cmyk.rb +62 -18
- data/lib/color/css.rb +27 -0
- data/lib/color/grayscale.rb +43 -13
- data/lib/color/hsl.rb +130 -0
- data/lib/color/palette.rb +4 -0
- data/lib/color/palette/gimp.rb +47 -12
- data/lib/color/palette/monocontrast.rb +41 -11
- data/lib/color/rgb-colors.rb +189 -0
- data/lib/color/rgb.rb +163 -27
- data/lib/color/rgb/metallic.rb +28 -0
- data/lib/color/yiq.rb +35 -9
- data/metaconfig +11 -2
- data/pre-setup.rb +12 -3
- data/tests/test_cmyk.rb +116 -0
- data/tests/test_css.rb +28 -0
- data/tests/test_gimp.rb +79 -0
- data/tests/test_grayscale.rb +87 -0
- data/tests/test_hsl.rb +93 -0
- data/tests/test_monocontrast.rb +145 -0
- data/tests/test_rgb.rb +160 -0
- data/tests/test_yiq.rb +81 -0
- data/tests/testall.rb +20 -0
- metadata +23 -8
data/lib/color/css.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Colour management with Ruby.
|
3
|
+
#
|
4
|
+
# Copyright 2005 Austin Ziegler
|
5
|
+
# http://rubyforge.org/ruby-pdf/
|
6
|
+
#
|
7
|
+
# Licensed under a MIT-style licence.
|
8
|
+
#
|
9
|
+
# $Id: css.rb,v 1.1 2005/08/05 23:07:20 austin Exp $
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'color'
|
13
|
+
|
14
|
+
# This namespace contains some CSS colour names.
|
15
|
+
module Color::CSS
|
16
|
+
# Returns the RGB colour for name or +nil+ if the name is not valid.
|
17
|
+
def self.[](name)
|
18
|
+
@colors[name.to_s.downcase.to_sym]
|
19
|
+
end
|
20
|
+
|
21
|
+
@colors = {}
|
22
|
+
Color::RGB.constants.each do |const|
|
23
|
+
next if const == "PDF_FORMAT_STR"
|
24
|
+
next if const == "Metallic"
|
25
|
+
@colors[const.downcase.to_sym] ||= Color::RGB.const_get(const)
|
26
|
+
end
|
27
|
+
end
|
data/lib/color/grayscale.rb
CHANGED
@@ -3,22 +3,32 @@
|
|
3
3
|
#
|
4
4
|
# Copyright 2005 Austin Ziegler
|
5
5
|
# http://rubyforge.org/ruby-pdf/
|
6
|
+
#
|
7
|
+
# Licensed under a MIT-style licence.
|
8
|
+
#
|
9
|
+
# $Id: grayscale.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
|
6
10
|
#++
|
7
11
|
|
8
12
|
# A colour object representing shades of grey. Used primarily in PDF
|
9
13
|
# document creation.
|
10
14
|
class Color::GrayScale
|
11
|
-
# The format
|
15
|
+
# The format of a DeviceGrey colour for PDF. In color-tools 2.0 this
|
16
|
+
# will be removed from this package and added back as a modification by
|
17
|
+
# the PDF::Writer package.
|
12
18
|
PDF_FORMAT_STR = "%.3f %s"
|
13
19
|
|
14
|
-
# Creates a greyscale colour object from fractional values 0
|
20
|
+
# Creates a greyscale colour object from fractional values 0..1.
|
21
|
+
#
|
22
|
+
# Color::GreyScale.from_fraction(0.5)
|
15
23
|
def self.from_fraction(g = 0)
|
16
24
|
color = Color::GrayScale.new
|
17
25
|
color.g = g
|
18
26
|
color
|
19
27
|
end
|
20
28
|
|
21
|
-
# Creates a greyscale colour object from percentages 0
|
29
|
+
# Creates a greyscale colour object from percentages 0..100.
|
30
|
+
#
|
31
|
+
# Color::GrayScale.new(50)
|
22
32
|
def initialize(g = 0)
|
23
33
|
@g = g / 100.0
|
24
34
|
end
|
@@ -27,18 +37,23 @@ class Color::GrayScale
|
|
27
37
|
# converted to GreyScale before comparison, so the comparison between a
|
28
38
|
# GreyScale colour and a non-GreyScale colour will be approximate and
|
29
39
|
# based on the other colour's #to_greyscale conversion. If there is no
|
30
|
-
# #to_greyscale conversion, this will raise an exception.
|
40
|
+
# #to_greyscale conversion, this will raise an exception. This will
|
41
|
+
# report that two GreyScale values are equivalent if they are within
|
42
|
+
# 1e-4 (0.0001) of each other.
|
31
43
|
def ==(other)
|
32
44
|
other = other.to_grayscale
|
33
|
-
other.kind_of?(Color::GrayScale) and
|
45
|
+
other.kind_of?(Color::GrayScale) and
|
46
|
+
((@g - other.g).abs <= 1e-4)
|
34
47
|
end
|
35
48
|
|
36
|
-
# Present the colour as a fill colour string for PDF.
|
49
|
+
# Present the colour as a DeviceGrey fill colour string for PDF. This
|
50
|
+
# will be removed from the default package in color-tools 2.0.
|
37
51
|
def pdf_fill
|
38
52
|
PDF_FORMAT_STR % [ @g, "g" ]
|
39
53
|
end
|
40
54
|
|
41
|
-
# Present the colour as a stroke colour string for PDF.
|
55
|
+
# Present the colour as a DeviceGrey stroke colour string for PDF. This
|
56
|
+
# will be removed from the default package in color-tools 2.0.
|
42
57
|
def pdf_stroke
|
43
58
|
PDF_FORMAT_STR % [ @g, "G" ]
|
44
59
|
end
|
@@ -50,19 +65,19 @@ class Color::GrayScale
|
|
50
65
|
|
51
66
|
# Present the colour as an HTML/CSS colour string.
|
52
67
|
def html
|
53
|
-
gs = "%02x" %
|
68
|
+
gs = "%02x" % to_255
|
54
69
|
"##{gs * 3}"
|
55
70
|
end
|
56
71
|
|
57
72
|
# Convert the greyscale colour to CMYK.
|
58
73
|
def to_cmyk
|
59
74
|
k = 1.0 - @g.to_f
|
60
|
-
Color::CMYK.
|
75
|
+
Color::CMYK.from_fraction(0, 0, 0, k)
|
61
76
|
end
|
62
77
|
|
63
78
|
# Convert the greyscale colour to RGB.
|
64
79
|
def to_rgb(ignored = true)
|
65
|
-
g =
|
80
|
+
g = to_255
|
66
81
|
Color::RGB.new(g, g, g)
|
67
82
|
end
|
68
83
|
|
@@ -74,12 +89,12 @@ class Color::GrayScale
|
|
74
89
|
# Lightens the greyscale colour by the stated percent.
|
75
90
|
def lighten_by(percent)
|
76
91
|
g = [@g + (@g * (percent / 100.0)), 1.0].min
|
77
|
-
Color::
|
92
|
+
Color::GrayScale.from_fraction(g)
|
78
93
|
end
|
79
94
|
|
80
95
|
# Darken the RGB hue by the stated percent.
|
81
96
|
def darken_by(percent)
|
82
|
-
g = [@g - (@g * (percent / 100.0)),
|
97
|
+
g = [@g - (@g * (percent / 100.0)), 0.0].max
|
83
98
|
Color::GrayScale.from_fraction(g)
|
84
99
|
end
|
85
100
|
|
@@ -94,6 +109,11 @@ class Color::GrayScale
|
|
94
109
|
Color::YIQ.from_fraction(y, i, q)
|
95
110
|
end
|
96
111
|
|
112
|
+
# Returns the HSL colour encoding of the greyscale value.
|
113
|
+
def to_hsl
|
114
|
+
Color::HSL.from_fraction(0, 0, @g)
|
115
|
+
end
|
116
|
+
|
97
117
|
# Returns the brightness value for this greyscale value; this is the
|
98
118
|
# greyscale value.
|
99
119
|
def brightness
|
@@ -101,5 +121,15 @@ class Color::GrayScale
|
|
101
121
|
end
|
102
122
|
|
103
123
|
attr_accessor :g
|
124
|
+
remove_method :g= ;
|
125
|
+
def g=(gg) #:nodoc:
|
126
|
+
gg = 1.0 if gg > 1
|
127
|
+
gg = 0.0 if gg < 0
|
128
|
+
@g = gg
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
module Color
|
133
|
+
# A synonym for Color::GrayScale.
|
134
|
+
GreyScale = GrayScale
|
104
135
|
end
|
105
|
-
Color::GreyScale = Color::GrayScale
|
data/lib/color/hsl.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
#--
|
2
|
+
# Colour management with Ruby.
|
3
|
+
#
|
4
|
+
# Copyright 2005 Austin Ziegler
|
5
|
+
# http://rubyforge.org/ruby-pdf/
|
6
|
+
#
|
7
|
+
# Licensed under a MIT-style licence.
|
8
|
+
#
|
9
|
+
# $Id: hsl.rb,v 1.2 2005/08/08 02:44:17 austin Exp $
|
10
|
+
#++
|
11
|
+
|
12
|
+
# An HSL colour object. Internally, the hue (#h), saturation (#s), and
|
13
|
+
# luminosity (#l) values are dealt with as fractional values in the range
|
14
|
+
# 0..1.
|
15
|
+
class Color::HSL
|
16
|
+
class << self
|
17
|
+
# Creates an HSL colour object from fractional values 0..1.
|
18
|
+
def from_fraction(h = 0.0, s = 0.0, l = 0.0)
|
19
|
+
colour = Color::HSL.new
|
20
|
+
colour.h = h
|
21
|
+
colour.s = s
|
22
|
+
colour.l = l
|
23
|
+
colour
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Compares the other colour to this one. The other colour will be
|
28
|
+
# converted to HSL before comparison, so the comparison between a HSL
|
29
|
+
# colour and a non-HSL colour will be approximate and based on the other
|
30
|
+
# colour's #to_hsl conversion. If there is no #to_hsl conversion, this
|
31
|
+
# will raise an exception. This will report that two HSL values are
|
32
|
+
# equivalent if all component values are within 1e-4 (0.0001) of each
|
33
|
+
# other.
|
34
|
+
def ==(other)
|
35
|
+
other = other.to_hsl
|
36
|
+
other.kind_of?(Color::HSL) and
|
37
|
+
((@h - other.h).abs <= 1e-4) and
|
38
|
+
((@s - other.s).abs <= 1e-4) and
|
39
|
+
((@l - other.l).abs <= 1e-4)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Creates an HSL colour object from the standard values of degrees and
|
43
|
+
# percentages (e.g., 145�, 30%, 50%).
|
44
|
+
def initialize(h = 0, s = 0, l = 0)
|
45
|
+
@h = h / 360.0
|
46
|
+
@s = s / 100.0
|
47
|
+
@l = l / 100.0
|
48
|
+
end
|
49
|
+
|
50
|
+
# Present the colour as an HTML/CSS colour string.
|
51
|
+
def html
|
52
|
+
to_rgb.html
|
53
|
+
end
|
54
|
+
|
55
|
+
# Converting to HSL as adapted from Foley and Van-Dam from
|
56
|
+
# http://www.bobpowell.net/RGBHSB.htm.
|
57
|
+
def to_rgb(ignored = nil)
|
58
|
+
# If luminosity is zero, the colour is always black.
|
59
|
+
return Color::RGB.new if @l == 0
|
60
|
+
# If luminosity is one, the colour is always white.
|
61
|
+
return Color::RGB.new(0xff, 0xff, 0xff) if @l == 1
|
62
|
+
# If saturation is zero, the colour is always a greyscale colour.
|
63
|
+
return Color::RGB.new(@l, @l, @l) if @s <= 1e-5
|
64
|
+
|
65
|
+
if (@l - 0.5) < 1e-5
|
66
|
+
tmp2 = @l * (1.0 + @s.to_f)
|
67
|
+
else
|
68
|
+
tmp2 = @l + @s - (@l * @s.to_f)
|
69
|
+
end
|
70
|
+
tmp1 = 2.0 * @l - tmp2
|
71
|
+
|
72
|
+
t3 = [ @h + 1.0 / 3.0, @h, @h - 1.0 / 3.0 ]
|
73
|
+
t3 = t3.map { |tmp3|
|
74
|
+
tmp3 += 1.0 if tmp3 < 1e-5
|
75
|
+
tmp3 -= 1.0 if (tmp3 - 1.0) > 1e-5
|
76
|
+
tmp3
|
77
|
+
}
|
78
|
+
|
79
|
+
rgb = t3.map do |tmp3|
|
80
|
+
if ((6.0 * tmp3) - 1.0) < 1e-5
|
81
|
+
tmp1 + ((tmp2 - tmp1) * tmp3 * 6.0)
|
82
|
+
elsif ((2.0 * tmp3) - 1.0) < 1e-5
|
83
|
+
tmp2
|
84
|
+
elsif ((3.0 * tmp3) - 2.0) < 1e-5
|
85
|
+
tmp1 + (tmp2 - tmp1) * ((2 / 3.0) - tmp3) * 6.0
|
86
|
+
else
|
87
|
+
tmp1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
Color::RGB.from_fraction(*rgb)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Converts to RGB then YIQ.
|
95
|
+
def to_yiq
|
96
|
+
to_rgb.to_yiq
|
97
|
+
end
|
98
|
+
|
99
|
+
# Converts to RGB then CMYK.
|
100
|
+
def to_cmyk
|
101
|
+
to_rgb.to_cmyk
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the luminosity (#l) of the colour.
|
105
|
+
def brightness
|
106
|
+
@l
|
107
|
+
end
|
108
|
+
def to_greyscale
|
109
|
+
Color::GrayScale.from_fraction(@l)
|
110
|
+
end
|
111
|
+
alias to_grayscale to_greyscale
|
112
|
+
|
113
|
+
attr_accessor :h, :s, :l
|
114
|
+
remove_method :h=, :s=, :l= ;
|
115
|
+
def h=(hh) #:nodoc:
|
116
|
+
hh = 1.0 if hh > 1
|
117
|
+
hh = 0.0 if hh < 0
|
118
|
+
@h = hh
|
119
|
+
end
|
120
|
+
def s=(ss) #:nodoc:
|
121
|
+
ss = 1.0 if ss > 1
|
122
|
+
ss = 0.0 if ss < 0
|
123
|
+
@s = ss
|
124
|
+
end
|
125
|
+
def l=(ll) #:nodoc:
|
126
|
+
ll = 1.0 if ll > 1
|
127
|
+
ll = 0.0 if ll < 0
|
128
|
+
@l = ll
|
129
|
+
end
|
130
|
+
end
|
data/lib/color/palette.rb
CHANGED
data/lib/color/palette/gimp.rb
CHANGED
@@ -3,30 +3,50 @@
|
|
3
3
|
#
|
4
4
|
# Copyright 2005 Austin Ziegler
|
5
5
|
# http://rubyforge.org/ruby-pdf/
|
6
|
+
#
|
7
|
+
# Licensed under a MIT-style licence.
|
8
|
+
#
|
9
|
+
# $Id: gimp.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
|
6
10
|
#++
|
7
11
|
|
8
12
|
require 'color/palette'
|
9
13
|
|
14
|
+
# A class that can read a GIMP (GNU Image Manipulation Program) palette
|
15
|
+
# file and provide a Hash-like interface to the contents. GIMP colour
|
16
|
+
# palettes are RGB values only.
|
17
|
+
#
|
18
|
+
# Because two or more entries in a GIMP palette may have the same name,
|
19
|
+
# all named entries are returned as an array.
|
20
|
+
#
|
21
|
+
# pal = Color::Palette::Gimp.from_file(my_gimp_palette)
|
22
|
+
# pal[0] => Color::RGB<...>
|
23
|
+
# pal["white"] => [ Color::RGB<...> ]
|
24
|
+
# pal["unknown"] => [ Color::RGB<...>, Color::RGB<...>, ... ]
|
25
|
+
#
|
26
|
+
# GIMP Palettes are always indexable by insertion order (an integer key).
|
10
27
|
class Color::Palette::Gimp
|
11
28
|
include Enumerable
|
12
29
|
|
13
30
|
class << self
|
31
|
+
# Create a GIMP palette object from the named file.
|
14
32
|
def from_file(filename)
|
15
33
|
File.open(filename, "rb") { |io| Color::Palette::Gimp.from_io(io) }
|
16
34
|
end
|
17
35
|
|
36
|
+
# Create a GIMP palette object from the provided IO.
|
18
37
|
def from_io(io)
|
19
38
|
Color::Palette::Gimp.new(io.read)
|
20
39
|
end
|
21
40
|
end
|
22
41
|
|
42
|
+
# Create a new GIMP palette.
|
23
43
|
def initialize(palette)
|
24
|
-
@colors =
|
44
|
+
@colors = []
|
45
|
+
@names = {}
|
25
46
|
@valid = false
|
26
47
|
@name = "(unnamed)"
|
27
48
|
|
28
49
|
index = 0
|
29
|
-
collision = {}
|
30
50
|
|
31
51
|
palette.split($/).each do |line|
|
32
52
|
line.chomp!
|
@@ -47,26 +67,41 @@ class Color::Palette::Gimp
|
|
47
67
|
|
48
68
|
line.gsub!(/^\s+/, '')
|
49
69
|
data = line.split(/\s+/, 4)
|
50
|
-
name = data.pop
|
70
|
+
name = data.pop.strip
|
51
71
|
data.map! { |el| el.to_i }
|
52
72
|
|
53
|
-
|
73
|
+
color = Color::RGB.new(*data)
|
54
74
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
@colors[name] = @colors[index]
|
59
|
-
end
|
60
|
-
end
|
75
|
+
@colors[index] = color
|
76
|
+
@names[name] ||= []
|
77
|
+
@names[name] << color
|
61
78
|
|
62
|
-
|
79
|
+
index += 1
|
80
|
+
end
|
63
81
|
end
|
64
82
|
|
65
83
|
def [](key)
|
66
|
-
|
84
|
+
if key.kind_of?(Numeric)
|
85
|
+
@colors[key]
|
86
|
+
else
|
87
|
+
@names[key]
|
88
|
+
end
|
67
89
|
end
|
68
90
|
|
91
|
+
# Loops through each colour.
|
69
92
|
def each
|
70
93
|
@colors.each { |el| yield el }
|
71
94
|
end
|
95
|
+
|
96
|
+
# Loops through each named colour set.
|
97
|
+
def each_name #:yields color_name, color_set:#
|
98
|
+
@names.each { |color_name, color_set| yield color_name, color_set }
|
99
|
+
end
|
100
|
+
|
101
|
+
# Returns true if this is believed to be a valid GIMP palette.
|
102
|
+
def valid?
|
103
|
+
@valid
|
104
|
+
end
|
105
|
+
|
106
|
+
attr_reader :name
|
72
107
|
end
|
@@ -3,6 +3,10 @@
|
|
3
3
|
#
|
4
4
|
# Copyright 2005 Austin Ziegler
|
5
5
|
# http://rubyforge.org/ruby-pdf/
|
6
|
+
#
|
7
|
+
# Licensed under a MIT-style licence.
|
8
|
+
#
|
9
|
+
# $Id: monocontrast.rb,v 1.3 2005/08/08 02:44:17 austin Exp $
|
6
10
|
#++
|
7
11
|
|
8
12
|
require 'color/palette'
|
@@ -26,7 +30,7 @@ class Color::Palette::MonoContrast
|
|
26
30
|
# 0:: The starting colour.
|
27
31
|
# +1..+5:: Lighter colours.
|
28
32
|
# -1..-5:: Darker colours.
|
29
|
-
|
33
|
+
attr_reader :background
|
30
34
|
# Hash of CSS foreground colour values.
|
31
35
|
#
|
32
36
|
# This is always 11 values:
|
@@ -34,30 +38,56 @@ class Color::Palette::MonoContrast
|
|
34
38
|
# 0:: The starting colour.
|
35
39
|
# +1..+5:: Lighter colours.
|
36
40
|
# -1..-5:: Darker colours.
|
37
|
-
|
41
|
+
attr_reader :foreground
|
42
|
+
|
43
|
+
DEFAULT_MINIMUM_BRIGHTNESS_DIFF = (125.0 / 255.0)
|
38
44
|
|
39
45
|
# The minimum brightness difference between the background and the
|
40
|
-
# foreground. Setting this value will
|
41
|
-
# the base colours. The default value
|
46
|
+
# foreground, and must be between 0..1. Setting this value will
|
47
|
+
# regenerate the palette based on the base colours. The default value
|
48
|
+
# for this is 125 / 255.0. If this value is set to +nil+, it will be
|
49
|
+
# restored to the default.
|
42
50
|
attr_accessor :minimum_brightness_diff
|
51
|
+
remove_method :minimum_brightness_diff= ;
|
43
52
|
def minimum_brightness_diff=(bd) #:nodoc:
|
44
|
-
|
53
|
+
if bd.nil?
|
54
|
+
@minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
|
55
|
+
elsif bd > 1.0
|
56
|
+
@minimum_brightness_diff = 1.0
|
57
|
+
elsif bd < 0.0
|
58
|
+
@minimum_brightness_diff = 0.0
|
59
|
+
else
|
60
|
+
@minimum_brightness_diff = bd
|
61
|
+
end
|
62
|
+
|
45
63
|
regenerate(@background[0], @foreground[0])
|
46
64
|
end
|
47
65
|
|
66
|
+
DEFAULT_MINIMUM_COLOR_DIFF = (500.0 / 255.0)
|
67
|
+
|
48
68
|
# The minimum colour difference between the background and the
|
49
|
-
# foreground. Setting this value will
|
50
|
-
# the base colours.
|
69
|
+
# foreground, and must be between 0..3. Setting this value will
|
70
|
+
# regenerate the palette based on the base colours. The default value
|
71
|
+
# for this is 500 / 255.0.
|
51
72
|
attr_accessor :minimum_color_diff
|
73
|
+
remove_method :minimum_color_diff= ;
|
52
74
|
def minimum_color_diff=(cd) #:noco:
|
53
|
-
|
75
|
+
if cd.nil?
|
76
|
+
@minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
|
77
|
+
elsif cd > 3.0
|
78
|
+
@minimum_color_diff = 3.0
|
79
|
+
elsif cd < 0.0
|
80
|
+
@minimum_color_diff = 0.0
|
81
|
+
else
|
82
|
+
@minimum_color_diff = cd
|
83
|
+
end
|
54
84
|
regenerate(@background[0], @foreground[0])
|
55
85
|
end
|
56
86
|
|
57
87
|
# Generate the initial palette.
|
58
88
|
def initialize(background, foreground = nil)
|
59
|
-
@minimum_brightness_diff =
|
60
|
-
@minimum_color_diff =
|
89
|
+
@minimum_brightness_diff = DEFAULT_MINIMUM_BRIGHTNESS_DIFF
|
90
|
+
@minimum_color_diff = DEFAULT_MINIMUM_COLOR_DIFF
|
61
91
|
|
62
92
|
regenerate(background, foreground)
|
63
93
|
end
|
@@ -140,7 +170,7 @@ class Color::Palette::MonoContrast
|
|
140
170
|
# Returns the contrast between to colours, a decimal value between 0 and
|
141
171
|
# 3. W3C accessibility guidelines for colour
|
142
172
|
# contrast[http://www.w3.org/TR/AERT#color-contrast] suggest that this
|
143
|
-
# value be at least approximately 1.96 (500 /
|
173
|
+
# value be at least approximately 1.96 (500 / 255.0) for proper contrast.
|
144
174
|
def color_diff(c1, c2)
|
145
175
|
r = (c1.r - c2.r).abs
|
146
176
|
g = (c1.g - c2.g).abs
|