Преобразование цветового кортежа RGB в шестизначный код на Python


87

Мне нужно преобразовать (0, 128, 64) в что-то вроде этого # 008040. Я не знаю, как назвать последнее, что затрудняет поиск.


См. Предыдущий ответ SO stackoverflow.com/questions/214359/… - из трех ответов тот, который набрал наибольшее количество голосов, включает автономный фрагмент кода Python для выполнения того, что, как я считаю, вам нужно.
Дуг

3
Вам нужен термин Hex Triplet. en.wikipedia.org/wiki/Hex_color#Hex_triplet
Марк Рэнсом

Для более общего вопроса с гораздо лучшими ответами, чем здесь: stackoverflow.com/a/57197866/624066
MestreLion

Ответы:


183

Используйте оператор формата %:

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

Обратите внимание, что он не будет проверять границы ...

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

Но действительно ли необходим двухзначный лимит? Пока значения RGB находятся в правильных пределах от 0 до 255, вам это не понадобится. Так что вы могли просто сделать'#%x%x%x' % (r, g, b)
другому

3
На самом деле теперь я вижу, что если у вас есть значение 0, его нужно дополнить еще одним 0. Таким образом, 02, чтобы сделать его двумя цифрами.
словами

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

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

При этом используется предпочтительный метод форматирования строк, как описано в PEP 3101 . Он также использует min()и maxдля обеспечения этого 0 <= {r,g,b} <= 255.

Обновление добавило функцию зажима, как предложено ниже.

Обновление Из заголовка вопроса и приведенного контекста должно быть очевидно, что это ожидает 3 целых числа в [0,255] и всегда будет возвращать цвет при передаче 3 таких целых чисел. Однако из комментариев это может быть не очевидно для всех, поэтому пусть будет указано прямо:

При intналичии трех значений будет возвращен действительный шестнадцатеричный триплет, представляющий цвет. Если эти значения находятся между [0,255], тогда он будет рассматривать их как значения RGB и возвращать цвет, соответствующий этим значениям.


20

Это старый вопрос, но для информации я разработал пакет с некоторыми утилитами, относящимися к цветам и палитре, и содержит функцию rgb2hex, которую вы искали для преобразования триплета в шестнадцатеричное значение (которое можно найти во многих других пакетах, например, matplotlib). Это на pypi

pip install colormap

а потом

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

Проверяется правильность введенных значений (значения должны быть от 0 до 255).


3
Я попытался использовать rgb2hex, но получил ошибку «ImportError: Нет модуля с именем easydev.tools». Вы можете предложить какое-нибудь решение?
Abhils

Попробуйте переустановить easydev. Затем «pip3 install easydev».
Шоунак Рэй

16

Я создал для него полную программу на Python, следующие функции могут преобразовывать rgb в шестнадцатеричный и наоборот.

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

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

Вы можете увидеть полный код и руководство по следующей ссылке: преобразование RGB в Hex и Hex в RGB с использованием Python


Это не работает для десятичного значения rgb. Вы можете предложить мне какое-нибудь решение?
Абхилс

Круглый. В конечном цвете не должно быть большой разницы.
Шоунак Рэй

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

или

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

python3 немного отличается

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

3

Обратите внимание, что это работает только с python3.6 и выше.

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

Вышеупомянутое эквивалентно:

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

Эта функция rgb2hex, примененная к (13,13,12), дает 0xDDC, но веб-сайт RGB to HEX дает его как 0x0D0D0C, и это также согласуется с идеей, что число должно быть 13 * 65536 + 13 * 256 + 12, а 0xDDC читается Python как 3548.
Ларс Эриксон

Цвета CSS несовместимы. Есть 6-значные шестнадцатеричные цвета, 3-значные шестнадцатеричные цвета, обозначение rgb с десятичными знаками и процентами, hsl и т. Д. Я настроил формулу, чтобы всегда обеспечивать шестизначные шестнадцатеричные цвета, и хотя я думаю, что это может быть более последовательным, Не уверен, что это правильнее.
Брайан Брюггеман

3

вы можете использовать лямбда и f-строки (доступно в 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))

Применение

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


1
Вызов лямбда напрямую не рекомендуется по ряду причин. Я использовал их вот так в проекте, который был рассмотрен, и все говорили одно и то же, а не напрямую.
MikeyB

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

background = RGB(0, 128, 64)

Я знаю, что однострочные сообщения в Python не обязательно приветствуются. Но бывают случаи, когда я не могу не воспользоваться тем, что позволяет парсер Python. Это тот же ответ, что и решение Дитриха Эппа (лучшее), но заключенный в однострочную функцию. Итак, спасибо, Дитрих!

Я использую его сейчас с tkinter :-)


2

Вот более полная функция для обработки ситуаций, в которых вы можете иметь значения RGB в диапазоне [0,1] или диапазоне [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))

1

В Python 3.6 вы можете использовать f-строки для очистки:

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

Конечно, вы можете поместить это в функцию , и в качестве бонуса значения округляются и преобразуются в int :

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

rgb2hex(*rgb)

1

Вы также можете использовать побитовые операторы, что довольно эффективно, хотя я сомневаюсь, что вы беспокоитесь об эффективности с чем-то вроде этого. Это также относительно чисто. Обратите внимание, что он не ограничивает и не проверяет границы. Это поддерживается как минимум с Python 2.7.17 .

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

И чтобы изменить его так, чтобы он начинался с символа #, вы можете:

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

1

Я действительно удивлен, что никто не предложил такой подход:

Для Python 2 и 3:

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

Python 3.6+:

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

Как функция:

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.