142

Working off Jeremy's response here: Converting hex color to RGB and vice-versa I was able to get a python program to convert preset colour hex codes (example #B4FBB8), however from an end-user perspective we can't ask people to edit code & run from there. How can one prompt the user to enter a hex value and then have it spit out a RGB value from there?

Here's the code I have thus far:

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):
    return '#%02x%02x%02x' % rgb

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'

print('Please enter your colour hex')

hex == input("")

print('Calculating...')
print(hex_to_rgb(hex()))

Using the line print(hex_to_rgb('#B4FBB8')) I'm able to get it to spit out the correct RGB value which is (180, 251, 184)

It's probably super simple - I'm still pretty rough with Python.

Community
  • 1
  • 1
Julian White
  • 1,603
  • 3
  • 12
  • 12
  • possible duplicate: https://stackoverflow.com/questions/5661725/format-ints-into-string-of-hex – User Jan 28 '19 at 22:27

15 Answers15

253

I believe that this does what you are looking for:

h = input('Enter hex: ').lstrip('#')
print('RGB =', tuple(int(h[i:i+2], 16) for i in (0, 2, 4)))

(The above was written for Python 3)

Sample run:

Enter hex: #B4FBB8
RGB = (180, 251, 184)

Writing to a file

To write to a file with handle fhandle while preserving the formatting:

fhandle.write('RGB = {}'.format( tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) ))
vallentin
  • 23,478
  • 6
  • 59
  • 81
John1024
  • 109,961
  • 14
  • 137
  • 171
  • Beautiful. Cuts 23 lines down to two, only suggestion is fixing to `for i in (0, 2, 4)))` – Julian White Apr 15 '15 at 11:43
  • Question, John1024, I'm writing the result (example #FFFFFF being (255, 255, 255)) to a file using f.write, it requests it be a string rather than a tuple. Is there any way I can convert it to a string preserving the commas and spaces? Cheers :) – Julian White Apr 15 '15 at 15:46
  • @JulianWhite No problem. I updated the answer using string formatting suitable for `f.write`. – John1024 Apr 15 '15 at 18:16
  • Getting error "TypeError: 'float' object cannot be interpreted as an integer" – Typewar Sep 05 '18 at 03:15
  • @Typewar Are you using python3? (This code would have to be modified if you needed to use it with the soon-to-be-obsolete python2.) What _exactly_ did you enter in response to the prompt? What is the full and complete error message that you see? – John1024 Sep 05 '18 at 06:24
  • Although implied it doesn't, this works in Python 2.7.12 as well. Just remember to `.lstrip('#')` the tkinter color coded being passed to your function. – WinEunuuchs2Unix Jun 13 '21 at 22:43
  • @WinEunuuchs2Unix I get your point but to obtain the same screen output from py2, one should either change the print command to `print 'RGB =', tuple(int(h[i:i+2], 16) for i in (0, 2, 4))` or else precede the print command with `from __future__ import print_function` – John1024 Jun 14 '21 at 04:23
  • 1
    @John1024 Gotcha. When I started out with `2.7.12` I was using `print` from the future I forgot all about that problem for others. – WinEunuuchs2Unix Jun 14 '21 at 10:25
  • 1
    For convenience, the reverse of this, converting a color triple `c` back to a hex string, is `'#' + ''.join(hex(x)[2:].zfill(2) for x in c)`. – Tyler Sep 23 '22 at 23:54
53

You can use ImageColor from Pillow.

>>> from PIL import ImageColor
>>> ImageColor.getcolor("#23a9dd", "RGB")
(35, 169, 221)
SuperNova
  • 25,512
  • 7
  • 93
  • 64
40

Just another option: matplotlib.colors module.

Quite simple:

>>> import matplotlib.colors
>>> matplotlib.colors.to_rgb('#B4FBB8')
(0.7058823529411765, 0.984313725490196, 0.7215686274509804)

Note that the input of to_rgb need not to be hexadecimal color format, it admits several color formats.

You can also use the deprecated hex2color

>>> matplotlib.colors.hex2color('#B4FBB8')
(0.7058823529411765, 0.984313725490196, 0.7215686274509804)

The bonus is that we have the inverse function, to_hex and few extra functions such as, rgb_to_hsv.

loved.by.Jesus
  • 2,266
  • 28
  • 34
19

A lazy option: webcolors package has a hex_to_rgb function.

vwrobel
  • 1,706
  • 15
  • 25
  • 4
    By the way, currently webcolors does not have a `hex_to_rgb` where the tuples are specified in decimal value in range 0 and 1 (say hex_to_rgb_decimal). But, you can use this code that imports numpy and webcolors: `tuple(numpy.array(webcolors.hex_to_rgb('#9C0006'))/255.0)` – Gürol Canbek Jun 03 '17 at 12:23
  • This was apparently the only solution that worked for me. – Typewar Sep 05 '18 at 03:13
11

PIL also has this function, in ImageColor.

from PIL import ImageColor

ImageColor.getrgb("#9b9b9b")

And if you want the numbers from 0 to 1

[i/256 for i in ImageColor.getrgb("#9b9b9b")]
Peter Mitrano
  • 2,132
  • 28
  • 31
  • In case you need values from 0…1: rgb = [i/256 for i in (ImageColor.getrgb("#9b9b9b"))] – Ideogram May 08 '20 at 07:00
  • 4
    I believe the last comment to be wrong. 255/256=0.99609. The values returned from `ImageColor.getrbb` are [0 ... 255], hard bounded by 255 upper limit. By dividing 256 you will never reach 1.0. Unless I am very wrong here, I suggest you change this to i/255. – ilykos Jun 06 '21 at 18:51
9

Try this:

def rgb_to_hex(rgb):
    return '%02x%02x%02x' % rgb

Usage:

>>> rgb_to_hex((255, 255, 195))
'ffffc3'

And for the reverse:

def hex_to_rgb(hexa):
    return tuple(int(hexa[i:i+2], 16)  for i in (0, 2, 4))

Usage:

>>> hex_to_rgb('ffffc3')
(255, 255, 195)
alvas
  • 115,346
  • 109
  • 446
  • 738
  • this is what I was looking for.. might want to handle hex strings with leading #, for example the way John1024 did it... something like hexa = hexa.lstrip('#') – Sam Murphy Mar 31 '23 at 15:25
6

This function will return the RGB values in float from a Hex code.

def hextofloats(h):
    '''Takes a hex rgb string (e.g. #ffffff) and returns an RGB tuple (float, float, float).'''
    return tuple(int(h[i:i + 2], 16) / 255. for i in (1, 3, 5)) # skip '#'

This function will return Hex code from RGB value.

def floatstohex(rgb):
    '''Takes an RGB tuple or list and returns a hex RGB string.'''
    return f'#{int(rgb[0]*255):02x}{int(rgb[1]*255):02x}{int(rgb[2]*255):02x}'
m02ph3u5
  • 3,022
  • 7
  • 38
  • 51
roberto
  • 577
  • 6
  • 5
5

As HEX codes can be like "#FFF", "#000", "#0F0" or even "#ABC" that only use three digits. These are just the shorthand version of writing a code, which are the three pairs of identical digits "#FFFFFF", "#000000", "#00FF00" or "#AABBCC".


This function is made in such a way that it can work with both shorthands as well as the full length of HEX codes. Returns RGB values if the argument hsl = False else return HSL values.

import re

def hex_to_rgb(hx, hsl=False):
    """Converts a HEX code into RGB or HSL.
    Args:
        hx (str): Takes both short as well as long HEX codes.
        hsl (bool): Converts the given HEX code into HSL value if True.
    Return:
        Tuple of length 3 consisting of either int or float values.
    Raise:
        ValueError: If given value is not a valid HEX code."""
    if re.compile(r'#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?$').match(hx):
        div = 255.0 if hsl else 0
        if len(hx) <= 4:
            return tuple(int(hx[i]*2, 16) / div if div else
                         int(hx[i]*2, 16) for i in (1, 2, 3))
        return tuple(int(hx[i:i+2], 16) / div if div else
                     int(hx[i:i+2], 16) for i in (1, 3, 5))
    raise ValueError(f'"{hx}" is not a valid HEX code.')

Here are some IDLE outputs.

>>> hex_to_rgb('#FFB6C1')
(255, 182, 193)

>>> hex_to_rgb('#ABC')
(170, 187, 204)

>>> hex_to_rgb('#FFB6C1', hsl=True)
(1.0, 0.7137254901960784, 0.7568627450980392)

>>> hex_to_rgb('#ABC', hsl=True)
(0.6666666666666666, 0.7333333333333333, 0.8)

>>> hex_to_rgb('#00FFFF')
(0, 255, 255)

>>> hex_to_rgb('#0FF')
(0, 255, 255)

>>> hex_to_rgb('#0FFG')  # When invalid hex is given.
ValueError: "#0FFG" is not a valid HEX code.
Saad
  • 3,340
  • 2
  • 10
  • 32
4

The following function will convert hex string to rgb values:

def hex_to_rgb(hex_string):
    r_hex = hex_string[1:3]
    g_hex = hex_string[3:5]
    b_hex = hex_string[5:7]
    return int(r_hex, 16), int(g_hex, 16), int(b_hex, 16)

This will convert the hexadecimal_string to decimal number

int(hex_string, 16)

For example:

int('ff', 16) # Gives 255 in integer data type
Gabriel Chung
  • 1,527
  • 1
  • 18
  • 30
2

There are two small errors here!

hex == input("")

Should be:

user_hex = input("")

You want to assign the output of input() to hex, not check for comparison. Also, as mentioned in comments (@koukouviou) don't override hex, instead call it something like user_hex.

Also:

print(hex_to_rgb(hex()))

Should be:

print(hex_to_rgb(user_hex))

You want to use the value of hex, not the type's callable method (__call__).

Matt Davidson
  • 728
  • 4
  • 9
2

All the answers I've seen involve manipulation of a hex string. In my view, I'd prefer to work with encoded integers and RGB triples themselves, not just strings. This has the benefit of not requiring that a color be represented in hexadecimal-- it could be in octal, binary, decimal, what have you.

Converting an RGB triple to an integer is easy.

rgb = (0xc4, 0xfb, 0xa1) # (196, 251, 161)

def rgb2int(r,g,b):
    return (256**2)*r + 256*g + b

c = rgb2int(*rgb) # 12909473
print(hex(c))     # '0xc4fba1'

We need a little more math for the opposite direction. I've lifted the following from my answer to a similar Math exchange question.

c = 0xc4fba1

def int2rgb(n):
    b = n % 256
    g = int( ((n-b)/256) % 256 )      # always an integer
    r = int( ((n-b)/256**2) - g/256 ) # ditto
    return (r,g,b)

print(tuple(map(hex, int2rgb(c)))) # ('0xc4', '0xfb', '0xa1')

With this approach, you can convert to and from strings with ease.

terrygarcia
  • 477
  • 5
  • 22
1

The problem with your approach is that a user can input a hex code in many formats such as:

  • With or without a hash symbol (#ff0000 or ff0000)
  • Uppercase or lowercase (#ff0000, #FF0000)
  • Including or not including transparency (#ffff0000 or #ff0000ff or #ff0000)

colorir can be used to format and convert between color systems:

from colorir import HexRGB, sRGB
user_input = input("Enter the hex code:")
rgb = HexRGB(user_input).rgb()  # This is safe for pretty much any hex format
aleferna
  • 136
  • 6
0

This supports also RGBA converting and short form (#fff). It's pretty ugly, but it does the trick.


def parse_hex(h):
    if h[0]=="#":
        h=h[1:]
    try:
        col=int(h,16)
    except ValueError:
        raise ValueError("Invalid HEX string") from None

    l=len(h)
    if l== 6: #long form , no alpha
            return (col&0xff0000)>>16,(col&0xff00)>>8,(col&0xff),1
    elif l== 8: #long form, alpha
            scol = col >> 8
            return (scol&0xff0000)>>16,(scol&0xff00)>>8,(scol&0xff),(col&0xff)/255
    elif l == 3: #short form, no alpha
            return 17*((col&0xf00)>>8),17*((col&0xf0)>>4),17*(col&0xf),1
    elif l == 4: #short form, alpha
            print(hex(col))
            return 17*((col&0xf000)>>12),17*((col&0xf00)>>8),17*((col&0xf0)>>4),17*(col&0xf)/255
    else:
            raise ValueError("Invalid HEX string")
Adam Jenča
  • 582
  • 7
  • 20
0

#Converting Hex to RGB value in Python

def hex_to_rgb(h, opacity=.8):
r = g = b = 0
if len(h) == 4:
    r = int(("0x" + h[1] + h[1]), base=16)
    g = int(("0x" + h[2] + h[2]), base=16)
    b = int(("0x" + h[3] + h[3]), base=16)
elif len(h) == 7:
    r = int(("0x" + h[1] + h[2]), base=16)
    g = int(("0x" + h[3] + h[4]), base=16)
    b = int(("0x" + h[5] + h[6]), base=16)
if opacity:
    return f"rgb({r}, {g}, {b}, {opacity})"
return f"rgb({r}, {g}, {b})"
0

This takes the accepted answer, but also handles short form hex codes e.g. #fff, #000 that can be encountered in the wild.

h = input('Enter hex: ').lstrip('#')

if len(h == 3):
  h = ''.join([d + d for d in h])

print('RGB =', tuple(int(h[i:i+2], 16) for i in (0, 2, 4)))

gieoon
  • 129
  • 7