在 Python 中将十六进制转换为 RGB 值

在这里解决 Jeremy 的回答: 将十六进制颜色转换为 RGB,反之亦然我能够得到一个 Python 程序来转换预设的颜色十六进制代码(例如 # B4FBB8) ,但是从最终用户的角度来看,我们不能要求人们编辑代码并从那里运行。如何提示用户输入一个十六进制值,然后让它从那里输出一个 RGB 值?

以下是我目前为止的代码:

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

使用 print(hex_to_rgb('#B4FBB8'))行,我能够让它吐出正确的 RGB 值(180,251,184)

可能超级简单,我对 Python 还是很粗糙的。

145534 次浏览

这里有两个小错误!

hex == input("")

应该是:

user_hex = input("")

您希望将 input()的输出分配给 hex,而不是检查是否进行了比较。另外,正如注释(@koukouviou)中提到的那样,不要覆盖 hex,而是把它称为类似于 user_hex的东西。

另外:

print(hex_to_rgb(hex()))

应该是:

print(hex_to_rgb(user_hex))

您希望使用十六进制的值,而不是类型的可调用方法(__call__)。

我相信这就是你想要的:

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

(上面是为 Python 3编写的)

样本运行:

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

写入文件

在保留格式的同时写入带有句柄 fhandle的文件:

fhandle.write('RGB = {}'.format( tuple(int(h[i:i+2], 16) for i in (0, 2, 4)) ))

一个懒惰的选择: Webcolor 包有一个 hex_to_rgb函数。

此函数将以浮点形式从 巫术代码返回 RGB值。

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

此函数将从 RGB值返回 巫术代码。

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

我见过的所有答案都涉及到对十六进制字符串的操纵。在我看来,我更喜欢使用编码的整数和 RGB 三元组本身,而不仅仅是字符串。这样做的好处是不需要用十六进制表示颜色——可以用八进制、二进制、十进制等等。

将 RGB 三元组转换为整数很容易。

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'

我们需要对相反的方向做更多的计算。我从对类似 数学交换题的回答中提取了以下内容。

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

使用这种方法,您可以轻松地从字符串转换为字符串。

PIL 在 ImageColor 中也有这个函数。

from PIL import ImageColor


ImageColor.getrgb("#9b9b9b")

如果你想要0到1之间的数字

[i/256 for i in ImageColor.getrgb("#9b9b9b")]

您可以使用 ImageColor从枕头。

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

由于 巫术代码可以像 只使用三位数字的 ABC0、 ABC1、 ABC2甚至 "#ABC"这些只是写代码的速记版本,这是三对相同的数字 "#FFFFFF""#000000""#00FF00""#AABBCC"


这个函数是这样做的,它可以工作的两个速记以及整个长度的十六进制代码。如果参数 hsl = False else 返回 HSL 值,则返回 RGB 值。

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

下面是一些空闲输出。

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

只是另一个选择: Matplotlib 颜色模块。

很简单:

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

注意,to_rgb的输入不需要十六进制颜色格式,它允许多种颜色格式。

您还可以使用已废弃的 hex2color

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

额外的好处是,我们有反函数,abc0和一些额外的功能,如,rgb_to_hsv

下面的函数将把十六进制字符串转换为 rgb 值:

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)

这将把十六进制字符串转换为十进制数

int(hex_string, 16)

例如:

int('ff', 16) # Gives 255 in integer data type

试试这个:

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

用法:

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

反过来说:

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

用法:

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

这种方法的问题在于用户可以输入许多格式的十六进制代码,例如:

  • 使用或不使用散列符号(# ff0000或 ff0000)
  • 大写或小写(# ff0000,# FF0000)
  • 包括或不包括透明度(# ff0000或 # ff0000ff 或 # ff0000)

Color 可以用来在颜色系统之间进行格式化和转换:

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

这也支持 RGBA 转换和短格式(#fff)。这是相当难看,但它做的诀窍。


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