ChatGPT解决这个技术问题 Extra ChatGPT

Converting Hex to RGB value in Python

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.


v
vallentin

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)) ))

Beautiful. Cuts 23 lines down to two, only suggestion is fixing to for i in (0, 2, 4)))
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 :)
@JulianWhite No problem. I updated the answer using string formatting suitable for f.write.
Getting error "TypeError: 'float' object cannot be interpreted as an integer"
@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.
S
SuperNova

You can use ImageColor from Pillow.

>>> from PIL import ImageColor
>>> ImageColor.getcolor("#23a9dd", "RGB")
(35, 169, 221)

Hey @SuperNova how to get the name of color instead of pixel values?
hwy @Mvk1312. Please check this. stackoverflow.com/questions/9694165/…
l
loved.by.Jesus

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.


v
vwrobel

A lazy option: webcolors package has a hex_to_rgb function.


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)
This was apparently the only solution that worked for me.
P
Peter Mitrano

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")]

In case you need values from 0…1: rgb = [i/256 for i in (ImageColor.getrgb("#9b9b9b"))]
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.
m
m02ph3u5

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}'

S
Saad

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.

G
Gabriel Chung

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

I found this solution is fastest one.
M
Matt Davidson

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__).


It is better to avoid overriding hex. Maybe something like hex_in or similar is better
Good point, @koukouviou - Python reports it as built-in name.
t
terrygarcia

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.


Well the question was about hex.
It does not answer the question, but it gives insight into how it's done conceptually, so +1. (teach a man how to fish and so on... )
a
alvas

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)

a
aleferna2001

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