Converter uma tupla de cor RGB em um código de seis dígitos, em Python

87

Preciso converter (0, 128, 64) para algo como este # 008040. Não tenho certeza de como chamar o último, tornando a pesquisa difícil.

retângulo
fonte
Veja a resposta anterior do SO stackoverflow.com/questions/214359/… - das três respostas, a que tem mais votos inclui um trecho de código python independente para fazer o que acredito que você está procurando.
doug
3
O termo que você está procurando é Hex Triplet. en.wikipedia.org/wiki/Hex_color#Hex_triplet
Mark Ransom
Para uma pergunta mais geral, com respostas muito melhores do que aqui: stackoverflow.com/a/57197866/624066
MestreLion

Respostas:

183

Use o operador de formato %:

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

Observe que ele não verifica os limites ...

>>> '#%02x%02x%02x' % (0, -1, 9999)
'#00-1270f'
Dietrich Epp
fonte
O limite de 2 dígitos é realmente necessário? Contanto que os valores RGB estejam nos limites apropriados de 0-255, você não deve precisar deles. Então você poderia apenas fazer'#%x%x%x' % (r, g, b)
palavras para o caso,
3
Na verdade, agora vejo que se você tem um valor de 0, ele precisa ser preenchido com outro 0. Assim, o 02 para torná-lo dois dígitos.
palavras para o sábio
51
def clamp(x): 
  return max(0, min(x, 255))

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

Isso usa o método preferido de formatação de string, conforme descrito no PEP 3101 . Ele também usa min()e maxpara garantir isso 0 <= {r,g,b} <= 255.

Atualização adicionada à função de grampo conforme sugerido abaixo.

Atualização A partir do título da pergunta e do contexto dado, deve ficar óbvio que isso espera 3 ints em [0,255] e sempre retornará uma cor quando passar 3 ints. No entanto, a partir dos comentários, isso pode não ser óbvio para todos, portanto, deixe ser explicitamente declarado:

Fornecidos três intvalores, retornará um trio hexadecimal válido que representa uma cor. Se esses valores estiverem entre [0,255], ele os tratará como valores RGB e retornará a cor correspondente a esses valores.

Jesse Dhillon
fonte
20

Esta é uma questão antiga, mas para informação, desenvolvi um pacote com alguns utilitários relacionados a cores e mapas de cores e contém a função rgb2hex que você estava procurando para converter tripleto em valor hexa (que pode ser encontrado em muitos outros pacotes, por exemplo, matplotlib). Está em pypi

pip install colormap

e depois

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

A validade das entradas é verificada (os valores devem estar entre 0 e 255).

Thomas Cokelaer
fonte
3
Tentei usar rgb2hex, mas recebi um erro "ImportError: Nenhum módulo chamado easydev.tools". Você pode sugerir alguma solução para isso?
Abhils
Tente reinstalar o easydev. Então, 'pip3 install easydev'.
Shounak Ray
16

Eu criei um programa python completo para ele, as seguintes funções podem converter rgb em hexadecimal e 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')))

Você pode ver o código completo e o tutorial no seguinte link: RGB para Hex e conversão de Hex para RGB usando Python

Mohd Shibli
fonte
Não funciona para o valor decimal de rgb. Você pode me sugerir alguma solução para isso?
Abhils
Volta. Não deve haver uma grande diferença na cor final.
Shounak Ray
9
triplet = (0, 128, 64)
print '#'+''.join(map(chr, triplet)).encode('hex')

ou

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

python3 é ligeiramente diferente

from base64 import b16encode
print(b'#'+b16encode(bytes(triplet)))
John La Rooy
fonte
3

Observe que isso só funciona com python3.6 e superior.

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

O acima é equivalente a:

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
Brian Bruggeman
fonte
Esta função rgb2hex, aplicada a (13,13,12), dá 0xDDC, mas o site RGB para HEX dá como 0x0D0D0C, e isso também concorda com a ideia de que o número deve ser 13 * 65536 + 13 * 256 + 12, e 0xDDC é lido por Python como 3548.
Lars Ericson
As cores CSS são inconsistentes. Existem cores hexadecimais de 6 dígitos, cores hexadecimais de 3 dígitos, notação rgb com decimais e porcentagens, hsl, etc. Ajustei a fórmula para sempre fornecer cores hexadecimais de 6 dígitos e, embora eu ache que possa ser mais consistente, não tenho certeza se é mais correto.
Brian Bruggeman
3

você pode usar lambda e f-strings (disponíveis em 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))

uso

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

Kaneki
fonte
1
Chamar lambda's diretamente não é recomendado por uma série de razões. Usei-os assim em um projeto que foi revisado e todos disseram a mesma coisa, para não ligar diretamente.
MikeyB
2
def RGB(red,green,blue): return '#%02x%02x%02x' % (red,green,blue)

background = RGB(0, 128, 64)

Eu sei que one-liners em Python não são necessariamente vistos com gentileza. Mas há momentos em que não resisto a aproveitar as vantagens do que o analisador Python permite. É a mesma resposta da solução de Dietrich Epp (a melhor), mas resumida em uma função de linha única. Então, obrigado Dietrich!

Estou usando agora com tkinter :-)

MikeyB
fonte
2

Aqui está uma função mais completa para lidar com situações nas quais você pode ter valores RGB na faixa [0,1] ou na faixa [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))
Richard
fonte
1

No Python 3.6 , você pode usar strings f para tornar isso mais limpo:

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

Claro, você pode colocar isso em uma função e, como bônus, os valores são arredondados e convertidos para int :

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

rgb2hex(*rgb)
toto_tico
fonte
1

Você também pode usar operadores bit wise que são muito eficientes, embora eu duvide que você se preocupe com a eficiência com algo assim. Também é relativamente limpo. Observe que ele não fixa ou verifica os limites. Isso é suportado pelo menos desde o Python 2.7.17 .

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

E para alterá-lo para que comece com um # você pode fazer:

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

Estou realmente surpreso que ninguém sugeriu esta abordagem:

Para Python 2 e 3:

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

Python 3.6+:

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

Como uma função:

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

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