Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ANSI Color Specific RGB Sequence Bash

Tags:

ansi-escape

I know that in bash terminals a reliable way to change color is using ANSI escape sequences. For example:

echo -e "\033[0;31mbrown text\033[0;00m" 

should output

brown text (in brown) 

Is there a way to output color using a specific RGB set with ANSI? Say I want bright red:

echo -e "**\033[255:0:0m**red text\033[0;00m" 

Does this sort of thing exist?

I just want to use standard bash.

like image 848
Blue Ice Avatar asked Mar 28 '13 13:03

Blue Ice


1 Answers

Both answers here fail to mention the Truecolor ANSI support for 8bpc color. This will get the RGB color the OP originally asked for.

Instead of ;5, use ;2, and specify the R, G, and B values (0-255) in the following three control segments.

\x1b[38;2;40;177;249m 

To test if your terminal supports Truecolor:

printf "\x1b[38;2;40;177;249mTRUECOLOR\x1b[0m\n" 

On my machine, XTerm happily outputted the correct color; although, terminals that are modeled after terminals that predate modern RGB color generally will not support truecolor - make sure you know your target before using this particular variant of the escape code.


I'd also like to point out the 38 and the ;5/;2 - Blue Ice mentioned that 38 routes and then 5 changes the color. That is slightly incorrect.

38 is the xterm-256 extended foreground color code; 30-37 are simply 16-color foreground codes (with a brightness controlled by escape code 1 on some systems and the arguably-supported 90-97 non-standard 'bright' codes) that are supported by all vt100/xterm-compliant colored terminals.

The ;2 and ;5 indicate the format of the color, ultimately telling the terminal how many more sequences to pull: ;5 specifying an 8-bit format (as Blue Ice mentioned) requiring only 1 more control segment, and ;2 specifying a full 24-bit RGB format requiring 3 control segments.

These extended modes are technically "undocumented" and are completely implementation defined. As far as I know and can research, they are not governed by the ANSI committee.


For the so inclined, the 5; (256 color) format starts with the 16 original colors (both dark/light, so 30-37 and 90-97) as colors 0-15.

The proceeding 216 colors (16-231) are formed by a 3bpc RGB value offset by 16, packed into a single value.

The final 24 colors (232-256) are greyscale starting from a shade slightly lighter than black ranging up to a shade slightly darker than white. Some emulators interpret these steps as linear increments from (256 / 24) on all three channels, though I've come across some emulators that seem to explicitly define these values.

Here is a Javascript function that performs such a conversion, taking into account all of the greys.

function rgbToAnsi256(r, g, b) {     // we use the extended greyscale palette here, with the exception of     // black and white. normal palette only has 4 greyscale shades.     if (r === g && g === b) {         if (r < 8) {             return 16;         }          if (r > 248) {             return 231;         }          return Math.round(((r - 8) / 247) * 24) + 232;     }      var ansi = 16         + (36 * Math.round(r / 255 * 5))         + (6 * Math.round(g / 255 * 5))         + Math.round(b / 255 * 5);      return ansi; } 

So in a way, you can calculate 256 ANSI colors from initial RGB values by reducing them from 8 to 3 bits in order to form a 256 encoded value in the event you want to programmatically do so on terminals that do not support Truecolor.

like image 153
Qix - MONICA WAS MISTREATED Avatar answered Oct 12 '22 01:10

Qix - MONICA WAS MISTREATED