rectangletangle
rectangletangle

Reputation: 53051

Converting an RGB color tuple to a hexidecimal string

I need to convert (0, 128, 64) to something like this "#008040". I'm not sure what to call the latter, making searching difficult.

Upvotes: 167

Views: 187843

Answers (17)

Mohd Shibli
Mohd Shibli

Reputation: 988

I have created a full python program for it the following functions can convert rgb to hex and vice versa.

def rgb2hex(r,g,b):
    return "#{:02x}{:02x}{:02x}".format(r,g,b)

def hex2rgb(hexcode):
    return tuple(map(ord,hexcode[1:].decode('hex')))

You can see the full code and tutorial at the following link : RGB to Hex and Hex to RGB conversion using Python

Upvotes: 25

The rag on din
The rag on din

Reputation: 73

For all simple color conversion, matplotlib provide a module with a buch of function, among which :

  • hsv_to_rgb
  • rgb_to_hsv
  • to_hex
  • to_rgb
  • to_rgba

You just have to normalise your values between 0 and 1. In your case :

from matplotlib.colors import to_hex
t = (0, 128, 64)
to_hex(tuple(v/255. for v in t)) # returns '#008040'

Upvotes: 4

My course task required doing this without using for loops and other stuff, here is my bizarre solution lol.

color1 = int(input())
color2 = int(input())
color3 = int(input())

color1 = hex(color1).upper()
color2 = hex(color2).upper()
color3 = hex(color3).upper()


print('#'+ color1[2:].zfill(2)+color2[2:].zfill(2)+color3[2:].zfill(2))

Upvotes: 0

s3dev
s3dev

Reputation: 9731

If typing the formatting string three times seems a bit verbose...

The combination of bit shifts and an f-string will do the job nicely:

# Example setup.
>>> r, g, b = 0, 0, 195

# Create the hex string.
>>> f'#{r << 16 | g << 8 | b:06x}'
'#0000c3'

This also illustrates a method by which 'leading' zero bits are not dropped, if either the red or green channels are zero.

Upvotes: 1

reema dass
reema dass

Reputation: 43

''.join('%02x'%i for i in input)

can be used for hex conversion from int number

Upvotes: 0

MestreLion
MestreLion

Reputation: 13736

I'm truly surprised no one suggested this approach:

For Python 2 and 3:

'#' + ''.join('{:02X}'.format(i) for i in colortuple)

Python 3.6+:

'#' + ''.join(f'{i:02X}' for i in colortuple)

As a function:

def hextriplet(colortuple):
    return '#' + ''.join(f'{i:02X}' for i in colortuple)

color = (0, 128, 64)
print(hextriplet(color))
#008040

Upvotes: 15

SuperNova
SuperNova

Reputation: 27486

There is a package called webcolors. https://github.com/ubernostrum/webcolors

It has a method webcolors.rgb_to_hex

>>> import webcolors
>>> webcolors.rgb_to_hex((12,232,23))
'#0ce817'

Upvotes: 1

CeaselessQuokka
CeaselessQuokka

Reputation: 31

You can also use bit wise operators which is pretty efficient, even though I doubt you'd be worried about efficiency with something like this. It's also relatively clean. Note it doesn't clamp or check bounds. This has been supported since at least Python 2.7.17.

hex(r << 16 | g << 8 | b)

And to change it so it starts with a # you can do:

"#" + hex(243 << 16 | 103 << 8 | 67)[2:]

Upvotes: 3

Kaneki
Kaneki

Reputation: 109

you can use lambda and f-strings(available in python 3.6+)

rgb2hex = lambda r,g,b: f"#{r:02x}{g:02x}{b:02x}"
hex2rgb = lambda hx: (int(hx[0:2],16),int(hx[2:4],16),int(hx[4:6],16))

usage

rgb2hex(r,g,b) #output = #hexcolor hex2rgb("#hex") #output = (r,g,b) hexcolor must be in #hex format

Upvotes: 9

Brian Bruggeman
Brian Bruggeman

Reputation: 5324

Note that this only works with python3.6 and above.

def rgb2hex(color):
    """Converts a list or tuple of color to an RGB string

    Args:
        color (list|tuple): the list or tuple of integers (e.g. (127, 127, 127))

    Returns:
        str:  the rgb string
    """
    return f"#{''.join(f'{hex(c)[2:].upper():0>2}' for c in color)}"

The above is the equivalent of:

def rgb2hex(color):
    string = '#'
    for value in color:
       hex_string = hex(value)  #  e.g. 0x7f
       reduced_hex_string = hex_string[2:]  # e.g. 7f
       capitalized_hex_string = reduced_hex_string.upper()  # e.g. 7F
       string += capitalized_hex_string  # e.g. #7F7F7F
    return string

Upvotes: 4

Richard
Richard

Reputation: 61569

Here is a more complete function for handling situations in which you may have RGB values in the range [0,1] or the range [0,255].

def RGBtoHex(vals, rgbtype=1):
  """Converts RGB values in a variety of formats to Hex values.

     @param  vals     An RGB/RGBA tuple
     @param  rgbtype  Valid valus are:
                          1 - Inputs are in the range 0 to 1
                        256 - Inputs are in the range 0 to 255

     @return A hex string in the form '#RRGGBB' or '#RRGGBBAA'
"""

  if len(vals)!=3 and len(vals)!=4:
    raise Exception("RGB or RGBA inputs to RGBtoHex must have three or four elements!")
  if rgbtype!=1 and rgbtype!=256:
    raise Exception("rgbtype must be 1 or 256!")

  #Convert from 0-1 RGB/RGBA to 0-255 RGB/RGBA
  if rgbtype==1:
    vals = [255*x for x in vals]

  #Ensure values are rounded integers, convert to hex, and concatenate
  return '#' + ''.join(['{:02X}'.format(int(round(x))) for x in vals])

print(RGBtoHex((0.1,0.3,  1)))
print(RGBtoHex((0.8,0.5,  0)))
print(RGBtoHex((  3, 20,147), rgbtype=256))
print(RGBtoHex((  3, 20,147,43), rgbtype=256))

Upvotes: 5

Mike from PSG
Mike from PSG

Reputation: 5764

def RGB(red,green,blue): return '#%02x%02x%02x' % (red,green,blue)

background = RGB(0, 128, 64)

I know one-liners in Python aren't necessarily looked upon kindly. But there are times where I can't resist taking advantage of what the Python parser does allow. It's the same answer as Dietrich Epp's solution (the best), but wrapped up in a single line function. So, thank you Dietrich!

I'm using it now with tkinter :-)

Upvotes: 2

toto_tico
toto_tico

Reputation: 19047

In Python 3.6, you can use f-strings to make this cleaner:

rgb = (0,128, 64)
f'#{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}'

Of course you can put that into a function, and as a bonus, values get rounded and converted to int:

def rgb2hex(r,g,b):
    return f'#{int(round(r)):02x}{int(round(g)):02x}{int(round(b)):02x}'

rgb2hex(*rgb)

Upvotes: 9

Thomas Cokelaer
Thomas Cokelaer

Reputation: 1059

This is an old question but for information, I developed a package with some utilities related to colors and colormaps and contains the rgb2hex function you were looking to convert triplet into hexa value (which can be found in many other packages, e.g. matplotlib). It's on pypi

pip install colormap

and then

>>> from colormap import rgb2hex
>>> rgb2hex(0, 128, 64)
'##008040'

Validity of the inputs is checked (values must be between 0 and 255).

Upvotes: 23

Jesse Dhillon
Jesse Dhillon

Reputation: 7997

def clamp(x): 
  return max(0, min(x, 255))

"#{0:02x}{1:02x}{2:02x}".format(clamp(r), clamp(g), clamp(b))

This uses the preferred method of string formatting, as described in PEP 3101. It also uses min() and max to ensure that 0 <= {r,g,b} <= 255.

Update added the clamp function as suggested below.

Update From the title of the question and the context given, it should be obvious that this expects 3 ints in [0,255] and will always return a color when passed 3 such ints. However, from the comments, this may not be obvious to everyone, so let it be explicitly stated:

Provided three int values, this will return a valid hex triplet representing a color. If those values are between [0,255], then it will treat those as RGB values and return the color corresponding to those values.

Upvotes: 71

John La Rooy
John La Rooy

Reputation: 304503

triplet = (0, 128, 64)
print '#'+''.join(map(chr, triplet)).encode('hex')

or

from struct import pack
print '#'+pack("BBB",*triplet).encode('hex')

python3 is slightly different

from base64 import b16encode
print(b'#'+b16encode(bytes(triplet)))

Upvotes: 10

Dietrich Epp
Dietrich Epp

Reputation: 213847

Use the format operator %:

>>> '#%02x%02x%02x' % (0, 128, 64)
'#008040'

Note that it won't check bounds...

>>> '#%02x%02x%02x' % (0, -1, 9999)
'#00-1270f'

Upvotes: 278

Related Questions