bash - Valores RGB de los colores en el índice de colores extendido de Ansi(17-255)




shell terminal (2)

La tabla de 256 colores y su partición.

La gama de colores de un terminal de 256 colores consta de 4 partes, a menudo 5, en cuyo caso realmente obtiene 258 colores:

  1. Los números de color del 0 al 7 son los colores de terminal predeterminados, cuyo valor RGB real no está estandarizado y, a menudo, se puede configurar.

  2. Los números de color del 8 al 15 son los colores "brillantes". La mayoría de las veces estos son un tono más claro del color con el índice - 8. Tampoco están estandarizados y, a menudo, se pueden configurar. Dependiendo de la terminal y el shell, a menudo se usan en lugar de o junto con fuentes tipográficas en negrita.

  3. Los números de color 16 a 231 son colores RGB. Estos 216 colores están definidos por 6 valores en cada uno de los tres ejes RGB. Es decir, en lugar de los valores 0 a 255, cada color solo varía de 0 a 5.

    El número de color se calcula así:

    number = 16 + 36 * r + 6 * g + b

    con r , g y b en el rango 0 - 5.

  4. Los números de colores del 232 al 255 son en escala de grises con 24 tonos de gris desde oscuro a claro.

  5. Los colores por defecto para el primer plano y el fondo. En muchos terminales, pueden configurarse independientemente de los 256 colores indexados, lo que da dos colores adicionales configurables. Los obtiene cuando no configura ningún otro color o deshabilita otros colores (es decir, print '\e[m' ).

Algunas fuentes:

  • urxvt urxvt:

    Además de los colores de fondo y fondo predeterminados, urxvt puede mostrar hasta 88/256 colores: 8 colores ANSI más versiones de alta intensidad (potencialmente negrita / intermitente) de los mismos, y 72 (o 240 en el modo de 256 colores) organizados en un cubo RGB de color de 4x4x4 (o 6x6x6) más una rampa de escala de grises de 8 (24) colores.

  • xterm manual de xterm :

    Estos especifican los colores para la extensión de 256 colores. Los valores de recursos predeterminados son para los colores del 16 al 231 para crear un cubo de color de 6x6x6, y los colores del 232 al 255 para crear una rampa de escala de grises.

  • Artículo de Wikipedia sobre códigos de escape ANSI (que a su vez carece de una cita sobre el tema)

Valores RGB predeterminados

Teóricamente, para obtener un rango de colores igualmente distribuidos, los valores RGB para los colores en el rango 16 - 231 se podrían calcular de la siguiente manera:

# example in Python: // is integer divison, % is modulo
rgb_R = ((number - 16) // 36) * 51
rgb_G = (((number - 16) % 36) // 6) * 51
rgb_B = ((number - 16) % 6) * 51

Pero parece que el método real es diferente:

Todos los emuladores de terminal que probé parecen seguir a XTerm y mapear los valores [0, 1, 2, 3, 4, 5] para rojo, verde y azul a los valores [0, 95, 135, 175, 215, 255] en el Ejes de color RGB. (Lo probé con XTerm (297) URxvt (v9.19), ROXTerm (2.8.1), gnome-terminal (3.6.2) y xfce4-terminal (0.6.3))

Los valores RGB para un índice dado se pueden calcular con este algoritmo:

# example in Python: 'a = b if c else d' is 'a = (c) ? b : d` in C, Perl, etc.
index_R = ((number - 16) // 36)
rgb_R = 55 + index_R * 40 if index_R > 0 else 0
index_G = (((number - 16) % 36) // 6)
rgb_G = 55 + index_G * 40 if index_G > 0 else 0
index_B = ((number - 16) % 6)
rgb_B = 55 + index_B * 40 if index_B > 0 else 0

La escala de grises parece seguir esta sencilla fórmula:

rgb_R = rgb_G = rgb_B = (number - 232) * 10 + 8

256colres.pl en la raíz de las fuentes XTerm (versión 313) utiliza un algoritmo similar para generar 256colres.h , que contiene las definiciones de color para el modo de 256 colores:

$line1="COLOR_RES(\"%d\",";
$line2="\tscreen.Acolors[%d],";
$line3="\tDFT_COLOR(\"rgb:%2.2x/%2.2x/%2.2x\")),\n";

# colors 16-231 are a 6x6x6 color cube
for ($red = 0; $red < 6; $red++) {
    for ($green = 0; $green < 6; $green++) {
    for ($blue = 0; $blue < 6; $blue++) {
        $code = 16 + ($red * 36) + ($green * 6) + $blue;
        printf($line1, $code);
        printf($line2, $code);
        printf($line3,
           ($red ? ($red * 40 + 55) : 0),
           ($green ? ($green * 40 + 55) : 0),
           ($blue ? ($blue * 40 + 55) : 0));
    }
    }
}

# colors 232-255 are a grayscale ramp, intentionally leaving out
# black and white
$code=232;
for ($gray = 0; $gray < 24; $gray++) {
    $level = ($gray * 10) + 8;
    $code = 232 + $gray;
    printf($line1, $code);
    printf($line2, $code);
    printf($line3,
       $level, $level, $level);
}

Mostrando los colores disponibles en un terminal.

Aquí hay una función zsh que imprime todos los colores en un terminal de 256 colores (si TERM está configurado en un valor de 256 colores):

function termcolors () 
{
    print TERM
    print -P "Foreground: >█<"
    print -P "Background: >%S█%s<\n"

    print "      0 1 2 3 4 5 6 7" 
    for b (0 1)
    do
        printf "%d %2d " $b $(( 8 * b ))
        for r (0 1 2 3 4 5 6 7)
        do
            c=$(( 8 * b + r ))
            print -nP "%K{$c}  %k"
        done
        printf " %2d\n" $(( 8 * b + 7 ))
    done

    print

    print RGB
    for r (0 1 2 3 4 5)
    do 
        print "$r $(( 16 + 36 * r )) - $(( 16 + 36 * r + 35 ))\n       0 1 2 3 4 5"
        for g (0 1 2 3 4 5)
        do
            printf "%d %3d " $g $(( 16 + 36 * r + 6 * g ))
            for b (0 1 2 3 4 5)
            do
                c=$(( 16 + 36 * r + 6 * g + b ))
                print -nP "%K{$c}  %k"
            done
            printf " %3d\n" $(( 16 + 36 * r + 6 * g + 5))
        done
        print
    done

    print

    print GRAY
    for g in $(seq 0 23)
    do
        c=$(( 232 + g ))
        printf "%2d %3d " $g $c
        print -P "%K{$c}  %k"
    done
}

Cambio de valores RGB durante el tiempo de ejecución

En algunos terminales (al menos xterm , gnome-terminal , termite y urxvt ) todos esos colores se pueden cambiar durante el tiempo de ejecución enviando una de las siguientes secuencias de control XTerm :

OSC 4; c ; spec BEL
OSC 4; c ; spec ST

dónde:

  • OSC es el carácter de escape ( \e o \033 ) seguido de ]
  • c es el número de color (0 - 255)
  • spec es una especificación de color (por ejemplo, red , #ff0000 , rgb:ff/00/00 rgbi:1/0/0 , rgbi:1/0/0 - lo que realmente funciona puede depender del terminal)
  • BEL es el carácter de campana ( \a o \007 )
  • ST es el terminador de cadena \e\\ o \033\\

Estas secuencias de control se pueden enviar simplemente imprimiéndolas con echo :

echo -en "\e]4;COLOR;SPEC\a"
echo -en "\e]4;COLOR;SPEC\a"

Por ejemplo, para establecer el color número 5 (generalmente un tono de magenta) en rojo, cualquiera de estos debería funcionar:

echo -en "\e]4;5;red\a"
echo -en "\e]4;5;#ff0000\e\\"
echo -en "\033]4;5;rgb:ff/00/00\007"

Esos colores se pueden restablecer a su valor predeterminado (configurado) con una de las secuencias de control

OSC 104 ; c BEL
OSC 104 ; c ST

Por lo tanto, el siguiente bucle restablecerá todos los colores de 0 a 255 a su valor configurado o predeterminado:

for c in {0..255}; do
  echo -en "\e]104;$c\a"
done

Para los colores de fondo y fondo predeterminados, las secuencias de control son OSC 10 ; spec BEL OSC 10 ; spec BEL y OSC 11 ; spec BEL OSC 11 ; spec BEL , respectivamente. Por ejemplo:

echo -en "\e]10;red\a"
echo -en "\e]11;green\a"

Se pueden reiniciar con OSC 110 BEL y OSC 111 BEL respectivamente:

echo -en "\e]110\a"
echo -en "\e]111\a"

Mi pregunta es en general shell scripting con colores ansi, pero como referencia estoy usando un Apple Mac OS X 10.9 Mavericks. Utilizo la aplicación de terminal "iTerm" como mi terminal por defecto, pero también verifiqué con la aplicación integrada de "terminal". Uso ZSH (5.0.7) como mi shell predeterminado, pero también verifiqué en BASH (3.2.51).

He estado tratando de averiguar si hay una lista de valores RGB para los códigos de escape Ansi de fondo / indexado de 256 colores indexados que están disponibles usando esc [38; 5; xm y esc [48; 5; xm donde x es un número del 0 al 255. He encontrado algunos scripts que imprimen los colores como bloques (usando el índice) pero quiero saber los valores rgb de cada uno de los colores en los índices.

Aquí hay un ejemplo de los códigos ansi en uso:

printf '\e[38;5;222;48;5;238m  Hi  \e[m\n'

(\ e puede ser reemplazado por \ 033 o \ x1b)

Entonces, básicamente, me pregunto si hay una lista o una configuración acordada para estos colores indexados. Por ejemplo, 232-255 parece ser siempre un degradado gris. Cada sitio que he encontrado que hace referencia a los colores extendidos simplemente dice cómo usarlo y no muestra ningún color específico.

Encontré algunas referencias a X11 y un archivo rgb.txt que al principio parecía que era lo que estaba buscando pero no parecen coincidir con los números de índice. Hay 752 colores en el archivo que encontré (la mayoría son duplicados, así que digamos 376, que aún es el 256). También hay 50 tonos de gris (100 si se cuentan los duplicados) pero los colores indexados de Ansi tienen 23, por lo que no parecen ser los mismos. Si estos de alguna manera contienen los colores en el índice de color extendido de ansi, ¿alguien tiene una lista de los nombres de cada índice?

PD. Sé que esc [38; 2; r; g: bm supuestamente puede establecer un color usando valores rgb pero no puedo hacer que funcione en mi Mac y estoy más interesado en los valores predeterminados para los colores indexados.

Algunos sitios: (¿solo se pueden publicar 2 debido a la baja reputación? Pero revisé muchos sitios)

Este tiene el rgb para los colores estándar pero no los extendidos.

Este tiene un gráfico de los colores pero no los valores rgb


Aquí están mis utilidades de color. El más útil es probablemente el convertidor Hex-> True, o RGB-> 256. Mucho de esto lo armé gracias a todos ustedes, ayuda <3

rgbtohex () {
  # usage) `rgbtohex 17 0 26` ==> 1001A
  # usage) `rgbtohex -h 17 0 26` ==> #1001A
  addleadingzero () { awk '{if(length($0)<2){printf "0";} print $0;}';}
  if [[ ${1} == "-h" ]]; then
    r=${2}; g=${3}; b=${4};h='#';
  else
    r=${1}; g=${2}; b=${3};h='';
  fi
  r=`echo "obase=16; ${r}" | bc | addleadingzero`
  g=`echo "obase=16; ${g}" | bc | addleadingzero`
  b=`echo "obase=16; ${b}" | bc | addleadingzero`
  echo "${h}${r}${g}${b}"
}

rgbto256 () {
  # usage: `rgbto256 0 95, 135` ==> 22
  echo "define trunc(x){auto os;os=scale;scale=0;x/=1;scale=os;return x;};" \
    "16 + 36 * trunc(${1}/51) + 6 * trunc(${2}/51) +" \
    " trunc(${3}/51)" | bc
  # XTerm Color Number = 16 + 36 * R + 6 * G + B | 0 <= R,G,B <= 5
}

hextorgb () {
  # usage) `hexttorgb "11001A" ==> 17 0 26
  # usage) `hexttorgb "#11001A" ==> 17 0 26
  hexinput=`echo ${1} | tr '[:lower:]' '[:upper:]'`  # uppercase-ing
  hexinput=`echo ${hexinput} | tr -d '#'`          # remove Hash if needed
  a=`echo ${hexinput} | cut -c-2`
  b=`echo ${hexinput} | cut -c3-4`
  c=`echo ${hexinput} | cut -c5-6`
  r=`echo "ibase=16; ${a}" | bc`
  g=`echo "ibase=16; ${b}" | bc`
  b=`echo "ibase=16; ${c}" | bc`
  echo ${r} ${g} ${b}
}

trueHexPrint () {
  # Generates Truecolor Escape Sequences from Hex Strings. (remove '\\' to use)
  # -fg     Prints as a foreground color. (default)
  # -bg     Prints as a background color.
  # usage) `trueHexPrint -fg "11001A" ==> '\e[38;2;17;0;26m'
  # usage) `trueHexPrint -bg "11001A" ==> '\e[48;2;17;0;26m'
  if [[ ${1} =~ "-fg" || ${1} =~ "-f" ]]; then
    fgbg=38; hexinput=${2};
  elif [[ ${1} =~ "-bg" || ${1} =~ "-b" ]]; then
    fgbg=48; hexinput=${2};
  else
    fgbg=38; hexinput=${1}
  fi
  hexinput=`echo ${hexinput} | tr '[:lower:]' '[:upper:]'`  # uppercase-ing
  hexinput=`echo ${hexinput} | tr -d '#'`               # remove Hash if needed
  a=`echo ${hexinput} | cut -c-2`
  b=`echo ${hexinput} | cut -c3-4`
  c=`echo ${hexinput} | cut -c5-6`
  r=`echo "ibase=16; ${a}" | bc`
  g=`echo "ibase=16; ${b}" | bc`
  b=`echo "ibase=16; ${c}" | bc`
  printf "\\\\e[${fgbg};2;${r};${g};${b}m" # Remove one set of '\\' to utilize
}

XColorTable () {
  i=16
  for ((r = 0; r <= 255; r+=40)); do # Do Tricolor
    for ((g = 0; g <= 255; g+=40)); do
      for ((b = 0; b <= 255; b+=40)); do
    echo "Color$((i++)) = (${r}, ${g}, ${b})"
        if ((b == 0)); then b=55; fi
      done
      if ((b == 0)); then g=55; fi
    done
    if ((r == 0)); then r=55; fi
  done
  for ((m = 8; m <= 238; m+=10)); do # Do Monochrome
    echo "Color$((i++)) = (${m}, ${m}, ${m})"
  done
}

#vim: ft=sh