class SimpleColor::RGB

Constants

ANSI_COLORS_16
COLOR_NAMES
GREY256
RGB_COLORS_ANSI

A list of color names for standard ansi colors, needed for 16/8 color fallback mode See en.wikipedia.org/wiki/ANSI_escape_code#Colors These are the xterm color palette

RGB_COLORS_ANSI_16
RGB_COLORS_ANSI_BRIGHT
TRUE_COLOR

Attributes

background[RW]
color[RW]
mode[RW]

Public Class Methods

new(*rgb, mode: :truecolor, background: false) click to toggle source
# File lib/simplecolor/rgb.rb, line 119
def initialize(*rgb, mode: :truecolor, background: false)
        raise WrongRGBColor.new(rgb) if rgb.empty?
        rgb=rgb.first if rgb.length==1
        raise WrongRGBColor.new(rgb) if rgb.nil?

        @init=rgb
        @color=rgb #should be an array for truecolor, a number otherwise
        @mode=color_mode(mode)
        @background=!!background
        
        case @mode
        when :truecolor
                unless @color&.size == 3 && @color&.all?{ |n| n.is_a? Numeric }
                        raise WrongRGBColor.new(rgb)
                end
                raise WrongRGBColor.new(rgb) unless rgb.all? do |c|
                        (0..255).include?(c)
                end
        when 256 #for 256 colors we are more lenient
                case rgb
                when Array
                        unless @color&.size == 3 && @color&.all?{ |n| n.is_a? Numeric }
                                raise WrongRGBColor.new(rgb)
                        end
                        raise WrongRGBColor.new(rgb) unless rgb.all? do |c|
                                (0..5).include?(c)
                        end
                        red, green, blue=rgb
                        @color=16 + 36 * red.to_i + 6 * green.to_i + blue.to_i
                when String, Symbol #for grey mode
                        if (m=rgb.to_s.match(/\Agr[ae]y(\d+)\z/))
                                @color=GREY256+m[1].to_i
                        else
                                raise WrongRGBColor.new(rgb)
                        end
                else
                        raise WrongRGBColor.new(rgb) unless @color.is_a?(Numeric)
                end
        when 8,16
                @color=ANSI_COLORS_16[rgb] if ANSI_COLORS_16.key?(rgb)
                raise WrongRGBColor.new(rgb) unless @color.is_a?(Numeric)
        end
end

Public Instance Methods

==(other) click to toggle source
# File lib/simplecolor/rgb.rb, line 163
def ==(other)
        [:color, :mode, :background].all? do |sym|
                self.public_send(sym) == other.public_send(sym)
        end
end
ansi(background: @background, convert: nil) click to toggle source

For true colors:

ESC[ 38;2;<r>;<g>;<b> m Select RGB foreground color
ESC[ 48;2;<r>;<g>;<b> m Select RGB background color
# File lib/simplecolor/rgb.rb, line 199
def ansi(background: @background, convert: nil)
        return self.convert(convert, only_down: true).ansi(background: background, convert: nil) if convert
        case @mode
        when 8, 16
                if @color < 8
                        "#{background ? 4 : 3}#{@color}"
                else
                        # Note that on_intense_* is not supported by terminals
                        # it is usually better to convert to 256 colors palette which is
                        # better supported
                        "#{background ? 10 : 9}#{@color-8}"
                end
        when 256
                "#{background ? 48 : 38};5;#{@color}"
        when :truecolor
                red, green, blue=@color
                "#{background ? 48 : 38};2;#{red};#{green};#{blue}"
        end
end
convert(mode, only_down: false) click to toggle source
# File lib/simplecolor/rgb.rb, line 219
def convert(mode, only_down: false)
        case color_mode(mode)
        when 8
                return to_8
        when 16
                return to_16 unless only_down and nbcolors < 16
        when 256
                return to_256 unless only_down and nbcolors < 256
        when :truecolor
                return to_truecolor unless only_down and nbcolors < TRUE_COLOR
        end
        self
end
nbcolors() click to toggle source
# File lib/simplecolor/rgb.rb, line 173
def nbcolors
        return TRUE_COLOR if @mode == :truecolor
        return @mode
end
rgb() click to toggle source
# File lib/simplecolor/rgb.rb, line 184
def rgb
        to_truecolor.color
end
rgb_color_distance(rgb2) click to toggle source
# File lib/simplecolor/rgb.rb, line 302
def rgb_color_distance(rgb2)
        if truecolor?
                @color.zip(self.class.rgb_values(rgb2)).inject(0){ |acc, (cur1, cur2)| acc + (cur1 - cur2)**2 }
        else
                to_truecolor.rgb_color_distance(rgb2)
        end
end
rgb_to_pool(color_pool) click to toggle source
# File lib/simplecolor/rgb.rb, line 310
def rgb_to_pool(color_pool)
        if truecolor?
                color_pool.min_by{ |col| rgb_color_distance(col) }
        else
                to_truecolor.rgb_to_pool(color_pool)
        end
end
to_16() click to toggle source
# File lib/simplecolor/rgb.rb, line 294
def to_16
        rgb16=self.class.rgb_colors16
        color_pool = rgb16.values
        closest=rgb_to_pool(color_pool)
        name=rgb16.key(closest)
        self.class.new(ANSI_COLORS_16[name], mode: 16)
end
to_256() click to toggle source
# File lib/simplecolor/rgb.rb, line 254
def to_256
        case @mode
        when 256
                return self
        when 8, 16
                return self.class.new(@color, mode: 256)
        else
                red,green,blue=@color

                gray_possible = true
                sep = 42.5

                while gray_possible
                        if red < sep || green < sep || blue < sep
                                gray = red < sep && green < sep && blue < sep
                                gray_possible = false
                        end
                        sep += 42.5
                end

                col=if gray
                        GREY256 + ((red.to_f + green.to_f + blue.to_f)/33).round
                else # rgb
                        [16, *[red, green, blue].zip([36, 6, 1]).map{ |color, mod|
                                (6 * (color.to_f / 256)).to_i * mod
                        }].inject(:+)
                end
                self.class.new(col, mode: 256)

        end
end
to_8() click to toggle source
# File lib/simplecolor/rgb.rb, line 286
def to_8
        rgb8=self.class.rgb_colors8
        color_pool = rgb8.values
        closest=rgb_to_pool(color_pool)
        name=rgb8.key(closest)
        self.class.new(ANSI_COLORS_16[name], mode: 8)
end
to_hex() click to toggle source
# File lib/simplecolor/rgb.rb, line 178
def to_hex
        r,g,b=rgb
        hexa = ->(c) {h=c.to_s(16).upcase; h.length == 1 ? "0#{h}" : h}
        "\##{hexa[r]}#{hexa[g]}#{hexa[b]}"
end
to_truecolor() click to toggle source
# File lib/simplecolor/rgb.rb, line 233
def to_truecolor
        case @mode
        when 8, 16
                name=ANSI_COLORS_16.key(@color)
                rgb=self.class.rgb_colors16[name]
                self.class.new(rgb)
        when 256
                if @color < 16
                        to_16.to_truecolor
                elsif @color < GREY256
                        red, green, blue=self.class.color256_to_rgb(@color)
                        self.class.new([red, green, blue].map {|c| (c * 256.0/7.0).round})
                else
                        grey=@color-GREY256
                        self.class.new([(grey*256.0/24.0).round]*3)
                end
        else
                self
        end
end
truecolor?() click to toggle source
# File lib/simplecolor/rgb.rb, line 169
def truecolor?
        @mode == :truecolor
end

Private Instance Methods

color_mode(mode) { |mode| ... } click to toggle source
# File lib/simplecolor/rgb.rb, line 105
        def color_mode(mode)
        case mode
        when true, :truecolor, TRUE_COLOR
                mode=:truecolor
        end
        case mode
        when 8, 16, 256, :truecolor
                yield mode if block_given?
                return mode
        else
                raise WrongRGBParameter.new(mode)
        end
end