6

Following from this answer, I am generating some evenly spaced colors in Python as follows:

>>> import colorsys
>>> num_colors = 22
>>> hsv_tuples = [(x*1.0/num_colors, 0.5, 0.5) for x in range(num_colors)]
>>> rgb_tuples = map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples)
>>> rgb_tuples
[(0.5, 0.25, 0.25), (0.5, 0.3181818181818182, 0.25), (0.5, 0.38636363636363635, 0.25), (0.5, 0.45454545454545453, 0.25), (0.4772727272727273, 0.5, 0.25), (0.4090909090909091, 0.5, 0.25), (0.34090909090909094, 0.5, 0.25), (0.2727272727272727, 0.5, 0.25), (0.25, 0.5, 0.2954545454545454), (0.25, 0.5, 0.36363636363636365), (0.25, 0.5, 0.43181818181818177), (0.25, 0.5, 0.5), (0.25, 0.4318181818181819, 0.5), (0.25, 0.36363636363636354, 0.5), (0.25, 0.2954545454545454, 0.5), (0.2727272727272727, 0.25, 0.5), (0.34090909090909083, 0.25, 0.5), (0.40909090909090917, 0.25, 0.5), (0.4772727272727273, 0.25, 0.5), (0.5, 0.25, 0.4545454545454546), (0.5, 0.25, 0.38636363636363646), (0.5, 0.25, 0.3181818181818181)]

Hows does one now convert from these ("coordinate?") RGB tuples back to RGB hex strings, e.g. #FF00AA? Probably a simple question, but not one I've been able to find the answer to.

Community
  • 1
  • 1
Bryce Thomas
  • 10,479
  • 26
  • 77
  • 126

3 Answers3

7

For each color, floor(color * 256), printed out in hexadecimal (padded to 2 places). e.g.:

In [1]: rgb_tuples = [(0.5, 0.25, 0.25), (0.5, 0.3181818181818182, 0.25), (0.5, 0.38636363636363635, 0.25), (0.5, 0.45454545454545453, 0.25), (0.4772727272727273, 0.5, 0.25), (0.4090909090909091, 0.5, 0.25), (0.34090909090909094, 0.5, 0.25), (0.2727272727272727, 0.5, 0.25), (0.25, 0.5, 0.2954545454545454), (0.25, 0.5, 0.36363636363636365), (0.25, 0.5, 0.43181818181818177), (0.25, 0.5, 0.5), (0.25, 0.4318181818181819, 0.5), (0.25, 0.36363636363636354, 0.5), (0.25, 0.2954545454545454, 0.5), (0.2727272727272727, 0.25, 0.5), (0.34090909090909083, 0.25, 0.5), (0.40909090909090917, 0.25, 0.5), (0.4772727272727273, 0.25, 0.5), (0.5, 0.25, 0.4545454545454546), (0.5, 0.25, 0.38636363636363646), (0.5, 0.25, 0.3181818181818181)]

In [2]: for (r,g,b) in rgb_tuples:
   ...:     print '%02x%02x%02x' % (int(r*255), int(g*255), int(b*255))
   ...:     
804040
805140
806240
807440
Brian Cain
  • 14,403
  • 3
  • 50
  • 88
4

1) Multiply the float by 256 and convert to an integer. If it's equal to 256, subtract 1.

EDIT: Since I'm getting a lot of confused comments, the reason why you have to multiply by 256 (subtract 1 if it ends up at 256) is so you get exactly the same number of float values corresponding to each integer output.

2) http://docs.python.org/2/library/string.html?highlight=hexadecimal#format-specification-mini-language

'x' Hex format. Outputs the number in base 16, using lower- case letters for the digits above 9.

Use that, make it upper case and plunk a # before it.

Patashu
  • 21,443
  • 3
  • 45
  • 53
  • 1
    I think you just want to multiply the float by 255, not 256, then take the `int()` of that. Think about it. – martineau Feb 09 '13 at 04:41
  • Assuming `int()` floors, then if you multiply by 255 only one float value out of the huge, huge number of float values will become a 255 - meaning the rest of the range, 0-254, will have disproportionately more in it. – Patashu Feb 09 '13 at 06:16
  • If you want proper rounding just use `int(round(f*255))`. – martineau Feb 09 '13 at 09:13
  • 1
    That's no good either - now 0 and 255 are represented by half as many entries as the other 1-254 entries. Imagine if you wanted to turn 0.0-1.0 to 0-2 and you did it by doing `int(round(f*2))` - 0.0 to 0.25 is 0, 0.25 to 0.75 is 1 and 0.75 to 1 is 2 - 1 gets the lion's share of the results!! – Patashu Feb 09 '13 at 11:15
  • While true computationally, what you say is imperceptible for this application of mapping 0.0-1.0 to the 0-255 range and generally not worth the extra effort required in the real world. – martineau Feb 09 '13 at 16:33
  • 1
    @martineau Perhaps, but if you don't know why the suggestion is wrong then you'll do it for less granular calculations and get bad bias. – Patashu Feb 10 '13 at 00:25
0

The most affective way to do this is to convert the base-1 decimal RGBs into the base-16 decimal, or HEX.

  r = int(input('R: '))
  g = int(input('G: '))
  b = int(input('B: '))
  def rgbToHex(r,g,b):
    rgb = [r,g,b]
    x = ''
    for i in rgb:
      x += format(i,'02x').upper()
    if x[0] == x[1] and x[2] == x[3] and x[4] == x[5]:
      x = x[0] + x[2] + x[4]
    return '#'+x
  print(rgbToHex(r,g,b))