lib/decolmor/main.rb in decolmor-1.1.2 vs lib/decolmor/main.rb in decolmor-1.2.0
- old
+ new
@@ -3,11 +3,11 @@
def self.included(base)
base.extend ClassMethods
end
#========= Set default rounding for HSL/HSV/HSB/CMYK conversion ========
-
+
# round 1 enough for lossless conversion RGB -> HSL/HSV/HSB -> RGB
# for lossless conversion HSL <==> HSV (HSB) better to use round 2
#
HSX_ROUND = 1
@@ -19,25 +19,32 @@
@hsx_round ||= HSX_ROUND
end
#========= HEX <==> RGB(A) =============================================
- def hex_to_rgb(hex, alpha_round = 3)
+ def hex_to_rgb(hex, alpha_round = 3, alpha_255: false)
hex = hex.gsub('#','')
hex = if [3, 4].include? hex.length
hex.chars.map{ |char| char * 2 }
else
hex.scan(/../)
end
rgb = hex.map(&:hex)
- rgb.size == 4 ? rgb + [(rgb.delete_at(3) / 255.to_f).round(alpha_round)] : rgb
+ if rgb.size == 4
+ rgb[3] = (rgb[3] / 255.to_f).round(alpha_round) unless alpha_255
+ end
+
+ rgb
end
- def rgb_to_hex(rgb)
- template = rgb.size == 3 ? "#%02X%02X%02X" : "#%02X%02X%02X%02X"
- rgb = rgb[0..2] + [(rgb[3] * 255).round] if rgb.size == 4
- template % rgb
+ def rgb_to_hex(rgb, alpha_255: false)
+ if rgb.size == 3
+ "#%02X%02X%02X" % rgb
+ else
+ rgb[3] = (rgb[3] * 255).round unless alpha_255
+ "#%02X%02X%02X%02X" % rgb
+ end
end
#=======================================================================
# simple generator RGB, you can set any channel(s)
@@ -101,36 +108,34 @@
saturation /= 100
lightness /= 100
# calculation intermediate values
a = saturation * [lightness, 1 - lightness].min
- converter = proc do |n|
- k = (n + hue / 30) % 12
- lightness - a * [-1, [k - 3, 9 - k, 1].min].max
- end
# calculation rgb & scaling into range 0..255
rgb = [0, 8, 4]
- rgb.map! { |channel| (converter.call(channel) * 255).round }
+ rgb.map! do |channel|
+ k = (channel + hue / 30) % 12
+ channel = lightness - a * [-1, [k - 3, 9 - k, 1].min].max
+ (channel * 255).round
+ end
alpha.nil? ? rgb : rgb + [alpha]
end
def hsv_to_rgb(hsv_arr)
hue, saturation, value, alpha = hsv_arr.map(&:to_f)
# scaling values into range 0..1
saturation /= 100
value /= 100
- # calculation intermediate values
- converter = proc do |n|
- k = (n + hue / 60) % 6
- value - value * saturation * [0, [k, 4 - k, 1].min].max
- end
-
# calculation rgb & scaling into range 0..255
rgb = [5, 3, 1]
- rgb.map! { |channel| (converter.call(channel) * 255).round }
+ rgb.map! do |channel|
+ k = (channel + hue / 60) % 6
+ channel = value - value * saturation * [0, [k, 4 - k, 1].min].max
+ (channel * 255).round
+ end
alpha.nil? ? rgb : rgb + [alpha]
end
alias_method :hsb_to_rgb, :hsv_to_rgb
@@ -144,26 +149,15 @@
# calculation chroma & intermediate values
chroma = (1 - (2 * lightness - 1).abs) * saturation
hue /= 60
x = chroma * (1 - (hue % 2 - 1).abs)
+ point = get_rgb_point(hue, chroma, x)
- # possible RGB points
- points = [[chroma, x, 0],
- [x, chroma, 0],
- [0, chroma, x],
- [0, x, chroma],
- [x, 0, chroma],
- [chroma, 0, x]]
- # point selection based on entering HUE input in range
- point = points.each_with_index.detect { |rgb_, n| (n..n + 1).include? hue }&.first
- # if point == nil (hue undefined)
- rgb = point || [0, 0, 0]
-
# calculation rgb & scaling into range 0..255
m = lightness - chroma / 2
- rgb.map! { |channel| ((channel + m) * 255).round }
+ rgb = point.map { |channel| ((channel + m) * 255).round }
alpha.nil? ? rgb : rgb + [alpha]
end
def hsv_to_rgb_alt(hsv_arr)
hue, saturation, value, alpha = hsv_arr.map(&:to_f)
@@ -173,26 +167,15 @@
# calculation chroma & intermediate values
chroma = value * saturation
hue /= 60
x = chroma * (1 - (hue % 2 - 1).abs)
+ point = get_rgb_point(hue, chroma, x)
- # possible RGB points
- points = [[chroma, x, 0],
- [x, chroma, 0],
- [0, chroma, x],
- [0, x, chroma],
- [x, 0, chroma],
- [chroma, 0, x]]
- # point selection based on entering HUE input in range
- point = points.each_with_index.detect { |rgb_, n| (n * (1 / 100.000)...n + 1).include? hue }&.first
- # if point == nil (hue undefined)
- rgb = point || [0, 0, 0]
-
# calculation rgb & scaling into range 0..255
m = value - chroma
- rgb.map! { |channel| ((channel + m) * 255).round }
+ rgb = point.map { |channel| ((channel + m) * 255).round }
alpha.nil? ? rgb : rgb + [alpha]
end
alias_method :hsb_to_rgb_alt, :hsv_to_rgb_alt
@@ -291,12 +274,28 @@
(blue - red) / chroma + 2
else
# blue is max
(red - green) / chroma + 4
end
- hue *= 60
- # make negative HUEs positive behind 360°
- 0 <= hue ? hue : hue + 360
+ hue * 60
+
+ # HUE will never leave the 0..360 range when RGB is within 0..255
+ # make negative HUEs positive
+ # 0 <= hue ? hue : hue + 360
+ end
+
+ # possible RGB points
+ # point selection based on entering HUE input in range
+ def get_rgb_point(hue, chroma, x)
+ case hue
+ when 0...1 then [chroma, x, 0]
+ when 1...2 then [x, chroma, 0]
+ when 2...3 then [0, chroma, x]
+ when 3...4 then [0, x, chroma]
+ when 4...5 then [x, 0, chroma]
+ when 5...6 then [chroma, 0, x]
+ else [0, 0, 0]
+ end
end
end
extend ClassMethods
end