How do I convert a hex triplet to an RGB tuple and back?

31,840

Solution 1

You can use a look-up table with some slicing and shifts — all relatively fast operations — to create a couple of functions that will work unchanged in both Python 2 and 3:

_NUMERALS = '0123456789abcdefABCDEF'
_HEXDEC = {v: int(v, 16) for v in (x+y for x in _NUMERALS for y in _NUMERALS)}
LOWERCASE, UPPERCASE = 'x', 'X'

def rgb(triplet):
    return _HEXDEC[triplet[0:2]], _HEXDEC[triplet[2:4]], _HEXDEC[triplet[4:6]]

def triplet(rgb, lettercase=LOWERCASE):
    return format(rgb[0]<<16 | rgb[1]<<8 | rgb[2], '06'+lettercase)

if __name__ == '__main__':
    print('{}, {}'.format(rgb('aabbcc'), rgb('AABBCC')))
    # -> (170, 187, 204), (170, 187, 204)

    print('{}, {}'.format(triplet((170, 187, 204)),
                          triplet((170, 187, 204), UPPERCASE)))
    # -> aabbcc, AABBCC

    print('{}, {}'.format(rgb('aa0200'), rgb('AA0200')))
    # -> (170, 2, 0), (170, 2, 0)

    print('{}, {}'.format(triplet((170, 2, 0)),
                          triplet((170, 2, 0), UPPERCASE)))
    # -> aa0200, AA0200

Solution 2

>>> import struct
>>> rgbstr='aabbcc'
>>> struct.unpack('BBB',rgbstr.decode('hex'))
(170, 187, 204)

and

>>> rgb = (50,100,150)
>>> struct.pack('BBB',*rgb).encode('hex')
'326496'

Solution 3

Trying to be pythonic:

>>> rgbstr='aabbcc'
>>> tuple(ord(c) for c in rgbstr.decode('hex'))
(170, 187, 204)
>>> tuple(map(ord, rgbstr.decode('hex'))
(170, 187, 204)

and

>>> rgb=(12,50,100)
>>> "".join(map(chr, rgb)).encode('hex')
'0c3264'

Solution 4

I found a simple way:

red, green, blue = bytes.fromhex("aabbcc")

Solution 5

with matplotlib

matplotlib uses RGB tuples with values between 0 and 1:

from matplotlib.colors import hex2color, rgb2hex

hex_color = '#00ff00'
rgb_color = hex2color(hex_color)
hex_color_again = rgb2hex(rgb_color)

both rgb_color and hex_color are in a format acceptable by matplotlib.

with webcolors

html uses RGB tuples with values between 0 and 255.

you can convert between them with the module webcolors, using the functions hex_to_rgb, rgb_to_hex

Share:
31,840
rectangletangle
Author by

rectangletangle

Updated on July 28, 2020

Comments

  • rectangletangle
    rectangletangle over 3 years

    I'd like to convert a hex triplet to an RGB tuple and then convert a tuple to a hex triplet.

  • Brian
    Brian over 13 years
    In python 3.0, replace str.decode('hex') with bytes.fromhex(str) . For the other direction, use binascii.hexlify to convert back to a string after packing.
  • spacedentist
    spacedentist over 13 years
    def int_to_hex_color(v): assert(len(v) == 3) return '#%02x%02x%02x' % v
  • spacedentist
    spacedentist over 13 years
    Sorry, your int_to_hex_color does not return correct results when some of the colour components have values < 16. int_to_hex_color((30,20,10)) -> '#1e14a'
  • martineau
    martineau over 13 years
    In Python 2.7 str is the name of a built-in type. This is also true in many earlier versions, I just don't recall offhand when it was introduced. Anyway, the point is that giving a variable that name isn't generally a good practice because it hides the type. This is still a good answer, IMHO.
  • martineau
    martineau about 10 years
    Converting this to work in Python 3.x is somewhat tricky -- especially (and surprisingly) the conversion to a hex triplet in the second part.
  • Samie Bencherif
    Samie Bencherif almost 10 years
    note that the rgb to hex fails if any of the input values are less than 16. e.g., rgb = (0, 255, 0) would result in "#0x0ff0"
  • rjh
    rjh almost 9 years
    If I'm not mistaken, binascii.hexlify yields a bytes object. You'd need to call .decode('utf-8') on that to get a string, right? The total command is binascii.hexlify(struct.pack('BBB', *rgb)).decode('utf-8'). I think '#%02x%02x%02x' % rgb is a lot simpler, and has the benefit of dealing with float values as well as integers.
  • Max Vyaznikov
    Max Vyaznikov over 8 years
    rgbstr.decode('hex') How it will looks like for python3?
  • unfa
    unfa almost 7 years
    This is the simplest solution out here, that doesn't even require importing any modules.
  • Marcel Wilson
    Marcel Wilson over 6 years
    bytearray.fromhex() for python 2.7
  • Marcel Wilson
    Marcel Wilson over 6 years
    This is not only simpler, it's also faster than using struct. More so if you return tuple instead of list.