lib/rubyXL/convenience_methods/color.rb
module RubyXL
module ColorConvenienceMethods
def get_rgb(workbook)
if rgb then
return rgb
elsif theme then
theme_color = workbook.theme.get_theme_color(theme)
rgb_color = theme_color && theme_color.a_srgb_clr
color_value = rgb_color && rgb_color.val
return nil if color_value.nil?
RubyXL::RgbColor.parse(color_value).to_hls.apply_tint(tint).to_rgb.to_s
end
end
end
module ColorConvenienceClasses
# https://ciintelligence.blogspot.com/2012/02/converting-excel-theme-color-and-tint.html
class RgbColor
attr_accessor :r, :g, :b, :a
def to_hls
hls_color = HlsColor.new
# Note that we are overriding accessors with local vars here:
r = self.r / 255.0
g = self.g / 255.0
b = self.b / 255.0
hls_color.a = (self.a || 0) / 255.0
min = [r, g, b].min
max = [r, g, b].max
delta = max - min
if (max == min) then
hls_color.h = hls_color.s = 0
hls_color.l = max
return hls_color
end
hls_color.l = (min + max) / 2
if (hls_color.l < 0.5) then
hls_color.s = delta / (max + min);
else
hls_color.s = delta / (2.0 - max - min);
end
hls_color.h = (g - b) / delta if (r == max)
hls_color.h = 2.0 + (b - r) / delta if (g == max)
hls_color.h = 4.0 + (r - g) / delta if (b == max)
hls_color.h *= 60;
hls_color.h += 360 if hls_color.h < 0
hls_color
end
def self.parse(str)
r, g, b, a = str.unpack('A2A2A2A2')
rgb_color = RgbColor.new
rgb_color.r = r && r.to_i(16)
rgb_color.g = g && g.to_i(16)
rgb_color.b = b && b.to_i(16)
rgb_color.a = a && a.to_i(16)
rgb_color
end
def to_s
if a && a != 0 then
format('%02x%02x%02x%02x', r, g, b, a)
else
format('%02x%02x%02x', r, g, b)
end
end
end
class HlsColor
attr_accessor :h, :l, :s, :a
def to_rgb
rgb_color = RgbColor.new
r = g = b = l
if s != 0 then
t1 = nil
if l < 0.5 then
t1 = l * (1.0 + s)
else
t1 = l + s - (l * s)
end
t2 = 2.0 * l - t1;
h = self.h / 360.0
t_r = h + (1.0 / 3.0)
r = set_color(t1, t2, t_r)
t_g = h;
g = set_color(t1, t2, t_g)
t_b = h - (1.0 / 3.0);
b = set_color(t1, t2, t_b)
end
rgb_color.r = (r * 255).round(0).to_i
rgb_color.g = (g * 255).round(0).to_i
rgb_color.b = (b * 255).round(0).to_i
rgb_color.a = (a * 255).round(0).to_i
rgb_color
end
def set_color(t1, t2, t3)
color = 0
t3 += 1.0 if (t3 < 0)
t3 -= 1.0 if (t3 > 1)
if (6.0 * t3 < 1) then
color = t2 + (t1 - t2) * 6.0 * t3;
elsif (2.0 * t3 < 1) then
color = t1;
elsif (3.0 * t3 < 2) then
color = t2 + (t1 - t2) * ((2.0 / 3.0) - t3) * 6.0;
else
color = t2;
end
color
end
private :set_color
def apply_tint(tint)
return self if tint.nil? || tint == 0
if tint < 0 then
self.l = l * (1.0 + tint);
else
self.l = l * (1.0 - tint) + tint;
end
self
end
end
end
RubyXL::Color.send(:include, RubyXL::ColorConvenienceMethods) # ruby 2.1 compat
include(RubyXL::ColorConvenienceClasses)
end