54

What is the most efficient way to do this?

1
  • 15
    You might want to define the language. This will make a difference in the algorithm chosen.
    – Adam Davis
    Commented Oct 18, 2008 at 1:35

10 Answers 10

179

In python:

def hex_to_rgb(value):
    """Return (red, green, blue) for the color given as #rrggbb."""
    value = value.lstrip('#')
    lv = len(value)
    return tuple(int(value[i:i + lv // 3], 16) for i in range(0, lv, lv // 3))

def rgb_to_hex(red, green, blue):
    """Return color as #rrggbb for the given color values."""
    return '#%02x%02x%02x' % (red, green, blue)

hex_to_rgb("#ffffff")           #==> (255, 255, 255)
hex_to_rgb("#ffffffffffff")     #==> (65535, 65535, 65535)
rgb_to_hex(255, 255, 255)       #==> '#ffffff'
rgb_to_hex(65535, 65535, 65535) #==> '#ffffffffffff'
7
  • 1
    Could you explain what's happening in the formatting for rbg_to_hex?
    – jpmc26
    Commented Apr 18, 2013 at 1:51
  • 2
    In the function, rgb is a tuple of 3 ints. That format string is just a # followed by three %02x which just gives a zero padded 2 digit hex value of the int. Commented Apr 19, 2013 at 15:24
  • 5
    I posted this so long ago and it's still one of my favorite chunks of python code (that I've written) Commented Apr 19, 2013 at 15:27
  • This is a great find, you don't mind if I use this in some GPL code of mine? :)
    – invert
    Commented Jun 8, 2013 at 7:51
  • 1
    For rgb_to_hex, you can always do *rbg in the argument list if you don't want to have to put a tuple in as a parameter, and it still works fine (causing errors if you don't put in three parameters). Commented Aug 26, 2014 at 0:36
43

In python conversion between hex and 'rgb' is also included in the plotting package matplotlib. Namely

import matplotlib.colors as colors

Then

colors.hex2color('#ffffff')        #==> (1.0, 1.0, 1.0)
colors.rgb2hex((1.0, 1.0, 1.0))    #==> '#ffffff'

The caveat is that rgb values in colors are assumed to be between 0.0 and 1.0. If you want to go between 0 and 255 you need to do a small conversion. Specifically,

def hex_to_rgb(hex_string):
    rgb = colors.hex2color(hex_string)
    return tuple([int(255*x) for x in rgb])

def rgb_to_hex(rgb_tuple):
    return colors.rgb2hex([1.0*x/255 for x in rgb_tuple])

The other note is that colors.hex2color only accepts valid hex color strings.

19

just real quick:

int r = ( hexcolor >> 16 ) & 0xFF;

int g = ( hexcolor >> 8 ) & 0xFF;

int b = hexcolor & 0xFF;

int hexcolor = (r << 16) + (g << 8) + b;
4
  • 2
    Careful of your operator precedence: + has higher precedence than << Commented Oct 18, 2008 at 2:29
  • 1
    Nice.. answer's been there for 1.5 years and no one caught that. Commented May 21, 2010 at 14:03
  • Um... if int is 16 bits. red is shifted to the bit bucket.
    – Harvey
    Commented Jan 4, 2015 at 20:28
  • @harvey, entirely true, as would 8-bit be an issue. Not sure how many 16-bit machines have C/Java compilers out there, but I'm sure it's more than when I wrote this answer 6+ years ago. Commented Jan 5, 2015 at 6:37
10

Real answer: Depends on what kind of hexadecimal color value you are looking for (e.g. 565, 555, 888, 8888, etc), the amount of alpha bits, the actual color distribution (rgb vs bgr...) and a ton of other variables.

Here's a generic algorithm for most RGB values using C++ templates (straight from ScummVM).

template<class T>
uint32 RGBToColor(uint8 r, uint8 g, uint8 b) {
return T::kAlphaMask |
       (((r << T::kRedShift) >> (8 - T::kRedBits)) & T::kRedMask) |
       (((g << T::kGreenShift) >> (8 - T::kGreenBits)) & T::kGreenMask) |
       (((b << T::kBlueShift) >> (8 - T::kBlueBits)) & T::kBlueMask);
}

Here's a sample color struct for 565 (the standard format for 16 bit colors):

template<>
struct ColorMasks<565> {
enum {
    highBits    = 0xF7DEF7DE,
    lowBits     = 0x08210821,
    qhighBits   = 0xE79CE79C,
    qlowBits    = 0x18631863,


    kBytesPerPixel = 2,

    kAlphaBits  = 0,
    kRedBits    = 5,
    kGreenBits  = 6,
    kBlueBits   = 5,

    kAlphaShift = kRedBits+kGreenBits+kBlueBits,
    kRedShift   = kGreenBits+kBlueBits,
    kGreenShift = kBlueBits,
    kBlueShift  = 0,

    kAlphaMask = ((1 << kAlphaBits) - 1) << kAlphaShift,
    kRedMask   = ((1 << kRedBits) - 1) << kRedShift,
    kGreenMask = ((1 << kGreenBits) - 1) << kGreenShift,
    kBlueMask  = ((1 << kBlueBits) - 1) << kBlueShift,

    kRedBlueMask = kRedMask | kBlueMask

};
};
7

Modifying Jeremy's python answer to handle short CSS rgb values like 0, #999, and #fff (which browsers would render as black, medium grey, and white):

def hex_to_rgb(value):
    value = value.lstrip('#')
    lv = len(value)
    if lv == 1:
        v = int(value, 16)*17
        return v, v, v
    if lv == 3:
        return tuple(int(value[i:i+1], 16)*17 for i in range(0, 3))
    return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))
3

You need only convert a value hex (in parts) to decimal and vice-versa. Also need considered, what value in hex may contains 6 or 3 characters (without character '#').

Implementation on the Python 3.5

"""Utils for working with colors."""

import textwrap


def rgb_to_hex(value1, value2, value3):
    """
    Convert RGB value (as three numbers each ranges from 0 to 255) to hex format.

    >>> rgb_to_hex(235, 244, 66)
    '#EBF442'
    >>> rgb_to_hex(56, 28, 26)
    '#381C1A'
    >>> rgb_to_hex(255, 255, 255)
    '#FFFFFF'
    >>> rgb_to_hex(0, 0, 0)
    '#000000'
    >>> rgb_to_hex(203, 244, 66)
    '#CBF442'
    >>> rgb_to_hex(53, 17, 8)
    '#351108'
    """

    for value in (value1, value2, value3):
        if not 0 <= value <= 255:
            raise ValueError('Value each slider must be ranges from 0 to 255')
    return '#{0:02X}{1:02X}{2:02X}'.format(value1, value2, value3)


def hex_to_rgb(value):
    """
    Convert color`s value in hex format to RGB format.

    >>> hex_to_rgb('fff')
    (255, 255, 255)
    >>> hex_to_rgb('ffffff')
    (255, 255, 255)
    >>> hex_to_rgb('#EBF442')
    (235, 244, 66)
    >>> hex_to_rgb('#000000')
    (0, 0, 0)
    >>> hex_to_rgb('#000')
    (0, 0, 0)
    >>> hex_to_rgb('#54433f')
    (84, 67, 63)
    >>> hex_to_rgb('#f7efed')
    (247, 239, 237)
    >>> hex_to_rgb('#191616')
    (25, 22, 22)
    """

    if value[0] == '#':
        value = value[1:]

    len_value = len(value)

    if len_value not in [3, 6]:
        raise ValueError('Incorect a value hex {}'.format(value))

    if len_value == 3:
        value = ''.join(i * 2 for i in value)
    return tuple(int(i, 16) for i in textwrap.wrap(value, 2))


if __name__ == '__main__':
    import doctest
    doctest.testmod()

Implementation on the JavaScript (adapted to the NodeJS with a support ES6)

const assert = require('assert');

/**
 * Return a color`s value in the hex format by passed the RGB format.
 * @param  {integer} value1 An value in ranges from 0 to 255
 * @param  {integer} value2 An value in ranges from 0 to 255
 * @param  {integer} value3 An value in ranges from 0 to 255
 * @return {string}        A color`s value in the hex format
 */
const RGBtoHex = (value1, value2, value3) => {
    const values = [value1, value2, value3];
    let result = '#';
    for (let i = 0; i < 3; i += 1) {
        // validation input
        if (values[i] < 0 || values[i] > 255) throw new Error('An each value of RGB format must be ranges from 0 to 255');

        // append to result values as hex with at least width 2
        result += (('0' + values[i].toString(16)).slice(-2));
    }
    return result.toUpperCase();
};


/**
 * Convert a value from the hex format to RGB and return as an array
 * @param  {int} value A color`s value in the hex format
 * @return {array}     Array values of the RGB format
 */
const hexToRGB = (value) => {
    let val = value;

    val = (value[0] === '#') ? value.slice(1) : value;

    if ([3, 6].indexOf(val.length) === -1) throw new Error(`Incorect a value of the hex format: ${value}`);

    if (val.length === 3) val = val.split('').map(item => item.repeat(2)).join('');

    return val.match(/.{2}/g).map(item => parseInt(`0x${item}`, 16));
};

assert.deepEqual(hexToRGB('fff'), [255, 255, 255]);
assert.deepEqual(hexToRGB('#fff'), [255, 255, 255]);
assert.deepEqual(hexToRGB('#000000'), [0, 0, 0]);
assert.deepEqual(hexToRGB('000000'), [0, 0, 0]);
assert.deepEqual(hexToRGB('#d7dee8'), [215, 222, 232]);
assert.deepEqual(hexToRGB('#1E2F49'), [30, 47, 73]);
assert.deepEqual(hexToRGB('#030914'), [3, 9, 20]);

assert.equal(RGBtoHex(255, 255, 255), '#FFFFFF');
assert.equal(RGBtoHex(0, 0, 0), '#000000');
assert.equal(RGBtoHex(96, 102, 112), '#606670');
assert.equal(RGBtoHex(199, 204, 214), '#C7CCD6');
assert.equal(RGBtoHex(22, 99, 224), '#1663E0');
assert.equal(RGBtoHex(0, 8, 20), '#000814');


module.exports.RGBtoHex = RGBtoHex;
module.exports.hexToRGB = hexToRGB;

Implementation on the C (intended for the C11 standart)


// a type for a struct of RGB color
typedef struct _ColorRGB {
    unsigned short int red;
    unsigned short int green;
    unsigned short int blue;
} colorRGB_t;


/*
    Convert a color`s value from the hex format to the RGB.
    Return -1 if a passed value in the hex format is not correct, otherwise - return 0;
 */
static int
convertColorHexToRGB(const char originValue[], colorRGB_t *colorRGB) {

    // a full value of color in hex format must constains 6 charapters
    char completedValue[6];
    size_t lenOriginValue;
    size_t lenCompletedValue;

    // an intermediary variable for keeping value in the hex format
    char hexSingleValue[3];

    // a temp pointer to char, need only to the strtol()
    char *ptr;

    // a variable for keeping a converted number in the hex to the decimal format
    long int number;

    // validation input
    lenOriginValue = strlen(originValue);
    if (lenOriginValue > 7 || lenOriginValue < 3) return -1;

    // copy value without sign '#', if found as first in the string
    (originValue[0] == '#') ? strcpy(completedValue, originValue + 1) : strcpy(completedValue, originValue);

    lenCompletedValue = strlen(completedValue);

    // if the value has only 3 charapters, dublicate an each after itself
    // but if not full version of the hex name of a color (6 charapters), return -1
    if (lenCompletedValue == 3) {
        completedValue[5] = completedValue[2];
        completedValue[4] = completedValue[2];
        completedValue[3] = completedValue[1];
        completedValue[2] = completedValue[1];
        completedValue[1] = completedValue[0];
    } else if (lenCompletedValue != 6) return -1;

    // convert string, by parts, to decimal values and keep it in a struct

    sprintf(hexSingleValue, "%c%c", completedValue[0], completedValue[1]);
    number = strtol(hexSingleValue, &ptr, 16);
    colorRGB->red = number;

    sprintf(hexSingleValue, "%c%c", completedValue[2], completedValue[3]);
    number = strtol(hexSingleValue, &ptr, 16);
    colorRGB->green = number;

    sprintf(hexSingleValue, "%c%c", completedValue[4], completedValue[5]);
    number = strtol(hexSingleValue, &ptr, 16);
    colorRGB->blue = number;

    return 0;
}


/*
    Convert a color`s value from the RGB format to the hex
 */
static int
convertColorRGBToHex(const colorRGB_t *colorRGB, char value[8]) {
    sprintf(value, "#%02X%02X%02X", colorRGB->red, colorRGB->green, colorRGB->blue);
    return 0;
}


/*
    Forming a string representation data in an instance of the structure colorRGB_t
 */
static int
getRGBasString(const colorRGB_t *colorRGB, char str[18]) {
    sprintf(str, "rgb(%d, %d, %d)", colorRGB->red, colorRGB->green, colorRGB->blue);
    return 0;
}


int main (int argv, char **argc)
{
    char str[18];
    char hex[8];

    colorRGB_t *colorRGB_;
    colorRGB_ = (colorRGB_t *)malloc(sizeof(colorRGB_));

    convertColorHexToRGB("fff", colorRGB_);
    getRGBasString(colorRGB_, str);
    printf("Hex 'fff' to RGB %s\n", str);
    convertColorRGBToHex(colorRGB_, hex);
    printf("RGB %s to hex '%s'\n", str, hex);

    convertColorHexToRGB("000000", colorRGB_);
    getRGBasString(colorRGB_, str);
    printf("Hex '000000' to RGB %s\n", str);
    convertColorRGBToHex(colorRGB_, hex);
    printf("RGB %s to hex '%s'\n", str, hex);

    convertColorHexToRGB("#000000", colorRGB_);
    getRGBasString(colorRGB_, str);
    printf("Hex '#000000' to RGB %s\n", str);
    convertColorRGBToHex(colorRGB_, hex);
    printf("RGB %s to hex '%s'\n", str, hex);

    convertColorHexToRGB("#FFF", colorRGB_);
    getRGBasString(colorRGB_, str);
    printf("Hex '#FFF' to RGB %s\n", str);
    convertColorRGBToHex(colorRGB_, hex);
    printf("RGB %s to hex '%s'\n", str, hex);

    free(colorRGB_);
}

A result after compilation (I am used the GCC)

Hex 'fff' to RGB rgb(255, 255, 255)
RGB rgb(255, 255, 255) to hex '#FFFFFF'
Hex '000000' to RGB rgb(0, 0, 0)
RGB rgb(0, 0, 0) to hex '#000000'
Hex '#000000' to RGB rgb(0, 0, 0)
RGB rgb(0, 0, 0) to hex '#000000'
Hex '#FFF' to RGB rgb(255, 255, 255)
RGB rgb(255, 255, 255) to hex '#FFFFFF'
2

A hex value is just RGB numbers represented in hexadecimal. So you just have to take each pair of hex digits and convert them to decimal.

Example:

#FF6400 = RGB(0xFF, 0x64, 0x00) = RGB(255, 100, 0)
1
  • He wrote an equation. RGB to hex is reading right to left. Hex to RGB is reading left to right. Commented Oct 18, 2008 at 1:43
1
#!/usr/bin/env python

import re
import sys

def hex_to_rgb(value):
  value = value.lstrip('#')
  lv = len(value)
  return tuple(int(value[i:i+lv/3], 16) for i in range(0, lv, lv/3))

def rgb_to_hex(rgb):
  rgb = eval(rgb)
  r = rgb[0]
  g = rgb[1]
  b = rgb[2]
  return '#%02X%02X%02X' % (r,g,b)

def main():
  color = raw_input("HEX [#FFFFFF] or RGB [255, 255, 255] value (no value quits program): ")
  while color:
    if re.search('\#[a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9][a-fA-F0-9]', color):
      converted = hex_to_rgb(color)
      print converted
    elif re.search('[0-9]{1,3}, [0-9]{1,3}, [0-9]{1,3}', color):
      converted = rgb_to_hex(color)
      print converted
    elif color == '':
      sys.exit(0)
    else:
      print 'You didn\'t enter a valid value!'
    color = raw_input("HEX [#FFFFFF] or RGB [255, 255, 255] value (no value quits program): ")

if __name__ == '__main__':
  main()
1

This is a fragment of code I created for my own use in c++11. you can send hex values or strings:

    void Color::SetColor(string color) {
    // try catch will be necessary if your string is not sanitized before calling this function.
         SetColor(std::stoul(color, nullptr, 16));
    }

    void Color::SetColor(uint32_t number) {
        B = number & 0xFF;
        number>>= 8;
        G = number & 0xFF;
        number>>= 8;
        R = number & 0xFF;
    }



 // ex:
 SetColor("ffffff");
 SetColor(0xFFFFFF);
0

Very Simple and Short implementation:

color_in_hex = 'FF00EE64' # Green Color
print('RGB =', tuple(int(color_in_hex[i:i+2], 16) for i in (0, 2, 4)))

Not the answer you're looking for? Browse other questions tagged or ask your own question.