Chuyển đổi bộ màu RGB thành mã sáu chữ số, bằng Python


87

Tôi cần chuyển đổi (0, 128, 64) thành một cái gì đó giống như thế này # 008040. Tôi không chắc nên gọi cái sau là gì, khiến việc tìm kiếm trở nên khó khăn.


Xem câu trả lời SO trước đó stackoverflow.com/questions/214359/… - trong số ba câu trả lời, câu trả lời có nhiều phiếu bầu nhất bao gồm một đoạn mã python độc lập để làm những gì tôi tin rằng bạn đang theo đuổi.
doug

3
Thuật ngữ bạn đang tìm kiếm là Hex Triplet. en.wikipedia.org/wiki/Hex_color#Hex_triplet
Mark Ransom

Đối với một câu hỏi tổng quát hơn, với câu trả lời tốt hơn nhiều so với tại đây: stackoverflow.com/a/57197866/624066
MestreLion

Câu trả lời:


183

Sử dụng toán tử định dạng %:

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

Lưu ý rằng nó sẽ không kiểm tra giới hạn ...

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

Mặc dù vậy, giới hạn 2 chữ số có thực sự cần thiết không? Miễn là các giá trị RGB nằm trong giới hạn thích hợp từ 0-255, bạn không nên cần đến nó. Vì vậy, bạn chỉ có thể làm'#%x%x%x' % (r, g, b)
wordsforthewise

3
Thực sự bây giờ tôi thấy rằng nếu bạn có giá trị 0, nó cần phải được đệm bằng một 0. Vì vậy, 02 để làm cho nó có hai chữ số.
wordsforthewise

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

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

Điều này sử dụng phương pháp định dạng chuỗi ưa thích, như được mô tả trong PEP 3101 . Nó cũng sử dụng min()maxđể đảm bảo rằng 0 <= {r,g,b} <= 255.

Cập nhật đã thêm chức năng kẹp như gợi ý bên dưới.

Cập nhật Từ tiêu đề của câu hỏi và ngữ cảnh đã cho, rõ ràng là điều này mong đợi 3 giá trị nguyên trong [0,255] và sẽ luôn trả về một màu khi chuyển 3 số nguyên đó. Tuy nhiên, từ các nhận xét, điều này có thể không rõ ràng đối với tất cả mọi người, vì vậy hãy để nó được nêu rõ ràng:

Được cung cấp ba intgiá trị, điều này sẽ trả về bộ ba hex hợp lệ đại diện cho một màu. Nếu các giá trị đó nằm trong khoảng [0,255], thì nó sẽ coi đó là các giá trị RGB và trả về màu tương ứng với các giá trị đó.


20

Đây là một câu hỏi cũ nhưng để biết thông tin, tôi đã phát triển một gói với một số tiện ích liên quan đến màu sắc và bản đồ màu và chứa hàm rgb2hex mà bạn đang tìm kiếm để chuyển đổi bộ ba thành giá trị hexa (có thể tìm thấy trong nhiều gói khác, ví dụ: matplotlib). Nó trên pypi

pip install colormap

và sau đó

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

Tính hợp lệ của các đầu vào được kiểm tra (giá trị phải từ 0 đến 255).


3
Tôi đã cố gắng sử dụng rgb2hex nhưng gặp lỗi "ImportError: No module name easydev.tools". Bạn có thể đề xuất bất kỳ giải pháp cho nó?
Abhils

Thử cài đặt lại easydev. Sau đó, 'pip3 install easydev'.
Shounak Ray

16

Tôi đã tạo một chương trình python đầy đủ cho nó các hàm sau có thể chuyển đổi rgb thành hex và ngược lại.

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

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

Bạn có thể xem toàn bộ mã và hướng dẫn tại liên kết sau: Chuyển đổi RGB sang Hex và Hex sang RGB bằng Python


Nó không hoạt động đối với giá trị thập phân của rgb. Bạn có thể đề xuất cho tôi bất kỳ giải pháp cho nó?
Abhils

Tròn. Không nên có sự khác biệt lớn về màu sắc cuối cùng.
Shounak Ray

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

hoặc là

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

python3 hơi khác một chút

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

3

Lưu ý rằng điều này chỉ hoạt động với python3.6 trở lên.

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

Ở trên là tương đương với:

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

Hàm rgb2hex này, được áp dụng cho (13,13,12), cho 0xDDC, nhưng trang web RGB thành HEX cho nó là 0x0D0D0C và điều này cũng đồng ý với ý tưởng vì số phải là 13 * 65536 + 13 * 256 + 12, và 0xDDC được Python đọc là 3548.
Lars Ericson

Màu CSS không nhất quán. Có các màu hex gồm 6 chữ số, màu hex 3 chữ số, ký hiệu rgb với số thập phân và phần trăm, hsl, v.v. Tôi đã điều chỉnh công thức để luôn cung cấp các màu hex 6 chữ số và mặc dù tôi nghĩ nó có thể nhất quán hơn, tôi Tôi không chắc nó đúng hơn.
Brian Bruggeman

3

bạn có thể sử dụng lambda và f-string (có sẵn trong 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))

sử dụng

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


1
Gọi trực tiếp lambda's không được khuyến khích vì một số lý do. Tôi đã sử dụng chúng như thế này trong một dự án đã được xem xét và mọi người đều nói như vậy, không gọi trực tiếp.
MikeyB

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

background = RGB(0, 128, 64)

Tôi biết một chữ trong Python không nhất thiết phải được nhìn nhận một cách tử tế. Nhưng có những lúc tôi không thể cưỡng lại việc tận dụng những gì mà trình phân tích cú pháp Python cho phép. Đó là câu trả lời giống như giải pháp của Dietrich Epp (tốt nhất), nhưng được gói gọn trong một hàm dòng duy nhất. Vì vậy, xin cảm ơn Dietrich!

Tôi đang sử dụng nó bây giờ với tkinter :-)


2

Đây là một chức năng hoàn chỉnh hơn để xử lý các tình huống trong đó bạn có thể có các giá trị RGB trong phạm vi [0,1] hoặc phạm vi [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

Trong Python 3.6 , bạn có thể sử dụng f-string để làm cho điều này rõ ràng hơn:

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

Tất nhiên, bạn có thể đặt nó vào một hàm và như một phần thưởng, các giá trị được làm tròn và chuyển đổi thành int :

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

rgb2hex(*rgb)

1

Bạn cũng có thể sử dụng các toán tử khôn ngoan khá hiệu quả, mặc dù tôi nghi ngờ bạn sẽ lo lắng về hiệu quả với những thứ như thế này. Nó cũng tương đối sạch sẽ. Lưu ý rằng nó không kẹp hoặc kiểm tra giới hạn. Điều này đã được hỗ trợ từ ít nhất Python 2.7.17 .

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

Và để thay đổi nó bắt đầu bằng dấu # bạn có thể làm:

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

1

Tôi thực sự ngạc nhiên không ai đề xuất cách tiếp cận này:

Đối với Python 2 và 3:

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

Python 3.6+:

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

Như một chức năng:

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

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.