Conversion d'un tuple de couleur RVB en un code à six chiffres, en Python

87

J'ai besoin de convertir (0, 128, 64) en quelque chose comme ceci # 008040. Je ne sais pas comment appeler ce dernier, ce qui rend la recherche difficile.

rectangle
la source
Voir la réponse précédente du SO stackoverflow.com/questions/214359/… - parmi les trois réponses, celle avec le plus de votes comprend un extrait de code Python pour faire ce que je pense que vous recherchez.
doug
3
Le terme que vous recherchez est Hex Triplet. en.wikipedia.org/wiki/Hex_color#Hex_triplet
Mark Ransom
Pour une question plus générale, avec de bien meilleures réponses qu'ici: stackoverflow.com/a/57197866/624066
MestreLion

Réponses:

183

Utilisez l'opérateur de format %:

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

Notez qu'il ne vérifie pas les limites ...

>>> '#%02x%02x%02x' % (0, -1, 9999)
'#00-1270f'
Dietrich Epp
la source
La limite à 2 chiffres est-elle vraiment nécessaire? Tant que les valeurs RVB sont dans les limites appropriées de 0 à 255, vous ne devriez pas en avoir besoin. Donc, vous pouvez simplement faire'#%x%x%x' % (r, g, b)
mots pour
3
En fait maintenant, je vois que si vous avez une valeur de 0, il doit être complété par un autre 0. Ainsi, le 02 pour en faire deux chiffres.
mots pour
51
def clamp(x): 
  return max(0, min(x, 255))

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

Cela utilise la méthode préférée de formatage de chaîne, comme décrit dans PEP 3101 . Il utilise également min()et maxpour garantir cela 0 <= {r,g,b} <= 255.

La mise à jour a ajouté la fonction de serrage comme suggéré ci-dessous.

Mise à jour À partir du titre de la question et du contexte donné, il devrait être évident que cela attend 3 pouces dans [0,255] et renverra toujours une couleur lorsqu'il est passé 3 pouces de ce type. Cependant, d'après les commentaires, cela peut ne pas être évident pour tout le monde, alors laissez-le être explicitement déclaré:

Si trois intvaleurs sont fournies , cela renverra un triplet hexadécimal valide représentant une couleur. Si ces valeurs sont comprises entre [0,255], il les traitera comme des valeurs RVB et renverra la couleur correspondant à ces valeurs.

Jesse Dhillon
la source
20

C'est une vieille question mais pour information, j'ai développé un package avec quelques utilitaires liés aux couleurs et aux couleurs et contient la fonction rgb2hex que vous cherchiez à convertir triplet en valeur hexa (qui peut être trouvée dans de nombreux autres packages, par exemple matplotlib). C'est sur pypi

pip install colormap

puis

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

La validité des entrées est vérifiée (les valeurs doivent être comprises entre 0 et 255).

Thomas Cokelaer
la source
3
J'ai essayé d'utiliser rgb2hex mais j'ai obtenu une erreur "ImportError: Aucun module nommé easydev.tools". Pouvez-vous suggérer une solution?
Abhils
Essayez de réinstaller easydev. Puis 'pip3 install easydev'.
Shounak Ray
16

J'ai créé un programme Python complet pour cela, les fonctions suivantes peuvent convertir rgb en hexadécimal et 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')))

Vous pouvez voir le code complet et le didacticiel sur le lien suivant: Conversion RVB vers Hex et Hex vers RVB avec Python

Mohd Shibli
la source
Cela ne fonctionne pas pour la valeur décimale de RVB. Pouvez-vous me suggérer une solution?
Abhils
Rond. Il ne devrait pas y avoir une énorme différence dans la couleur finale.
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 est légèrement différent

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

Notez que cela ne fonctionne qu'avec python3.6 et supérieur.

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

Ce qui précède est l'équivalent de:

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
la source
Cette fonction rgb2hex, appliquée à (13,13,12), donne 0xDDC, mais le site Web RGB to HEX le donne comme 0x0D0D0C, et cela concorde également avec l'idée que le nombre devrait être 13 * 65536 + 13 * 256 + 12, et 0xDDC est lu par Python comme 3548.
Lars Ericson
Les couleurs CSS sont incohérentes. Il y a des couleurs hexadécimales à 6 chiffres, des couleurs hexadécimales à 3 chiffres, une notation RVB avec décimales et pourcentages, hsl, etc. J'ai modifié la formule pour toujours fournir des couleurs hexadécimales à 6 chiffres, et même si je pense que cela peut être plus cohérent, je Je ne suis pas sûr que ce soit plus correct.
Brian Bruggeman
3

vous pouvez utiliser des chaînes lambda et f (disponible en 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

Kaneki
la source
1
L'appel direct de lambda n'est pas recommandé pour une foule de raisons. Je les ai utilisés comme ça sur un projet qui a été revu et tout le monde a dit la même chose, de ne pas appeler directement.
MikeyB
2
def RGB(red,green,blue): return '#%02x%02x%02x' % (red,green,blue)

background = RGB(0, 128, 64)

Je sais que les one-liners en Python ne sont pas forcément appréciés. Mais il y a des moments où je ne peux pas résister à profiter de ce que permet l'analyseur Python. C'est la même réponse que la solution de Dietrich Epp (la meilleure), mais enveloppée dans une fonction sur une seule ligne. Alors, merci Dietrich!

Je l'utilise maintenant avec tkinter :-)

MikeyB
la source
2

Voici une fonction plus complète pour gérer les situations dans lesquelles vous pouvez avoir des valeurs RVB dans la plage [0,1] ou la plage [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
la source
1

Dans Python 3.6 , vous pouvez utiliser des chaînes f pour rendre ce nettoyeur:

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

Bien sûr, vous pouvez mettre cela dans une fonction , et en prime, les valeurs sont arrondies et converties en int :

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

rgb2hex(*rgb)
toto_tico
la source
1

Vous pouvez également utiliser des opérateurs peu judicieux, ce qui est assez efficace, même si je doute que vous vous inquiétiez de l'efficacité avec quelque chose comme ça. C'est aussi relativement propre. Notez qu'il ne serre pas ou ne vérifie pas les limites. Cela est pris en charge depuis au moins Python 2.7.17 .

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

Et pour le changer pour qu'il commence par un #, vous pouvez faire:

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

Je suis vraiment surpris que personne n'ait suggéré cette approche:

Pour Python 2 et 3:

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

Python 3.6+:

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

En tant que fonction:

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

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