views:

1274

answers:

5

How can I convert an RGB integer to the corresponding RGB tuple (R,G,B)? Seems simple enough, but I can't find anything on google.

I know that for every RGB (r,g,b) you have the integer n = r256^2 + g256 + b, how can I solve the reverse in Python, IE given an n, I need the r,g,b values.

+3  A: 

From a RGB integer:

Blue =  RGBint mod 256
Green = RGBint / 256 mod 256
Red =   RGBint / 256 / 256 mod 256

This can be pretty simply implemented once you know how to get it. :)

Upd: Added python function. Not sure if there's a better way to do it, but this works on Python 3 and 2.4

def rgb_int2tuple(rgbint):
    return (rgbint // 256 // 256 % 256, rgbint // 256 % 256, rgbint % 256)

There's also an excellent solution that uses bitshifting and masking that's no doubt much faster that Nils Pipenbrinck posted.

Xorlev
Don't forget to use integer division and not float division.
Ignacio Vazquez-Abrams
Despite the fact that it uses integer division and modulo, I don't think my answer is deserving of a downrate.
Xorlev
No, it doesn't deserve a downvote. People haven't read the downvote-arrow tooltip and believe that downvoting means "I don't like this."
ΤΖΩΤΖΙΟΥ
Indeed. +5/-2 on a correct answer.
Xorlev
A: 

There's probably a shorter way of doing this:

dec=10490586
hex="%06x" % dec
r=hex[:2]
g=hex[2:4]
b=hex[4:6]
rgb=(r,g,b)

EDIT: this is wrong - gives the answer in Hex, OP wanted int. EDIT2: refined to reduce misery and failure - needed '%06x' to ensure hex is always shown as six digits [thanks to Peter Hansen's comment].

monojohnny
This will also fail miserably if the hex string doesn't have the expected six digits. Use "%06x" to avoid that.
Peter Hansen
+9  A: 

I'm not a Python expert by all means, but as far as I know it has the same operators as C.

If so this should work and it should also be a lot quicker than using modulo and division.

Blue =  RGBint & 255
Green = (RGBint >> 8) & 255
Red =   (RGBint >> 16) & 255

What it does it to mask out the lowest byte in each case (the binary and with 255.. Equals to a 8 one bits). For the green and red component it does the same, but shifts the color-channel into the lowest byte first.

Nils Pipenbrinck
+1 however speed advantage over a solution that uses % and // should be minimal. Certainly much faster than solutions with function calls (divmod, struct.[un]pack, etc).
John Machin
+4  A: 

I assume you have a 32-bit integer containing the RGB values (e.g. ARGB). Then you can unpack the binary data using the struct module:

# Create an example value (this represents your 32-bit input integer in this example).
# The following line results in exampleRgbValue = binary 0x00FF77F0 (big endian)
exampleRgbValue = struct.pack(">I", 0x00FF77F0)

# Unpack the value (result is: a = 0, r = 255, g = 119, b = 240)
a, r, g, b = struct.unpack("BBBB", exampleRgbValue)
AndiDog
struct.unpack("BBBB", struct.pack(">I", rgb_int)) is an awesome solution. +1
Xorlev
+1 Awesome indeed. Concise, slightly esoteric, yet still readable.
Jon Purdy
and would be awesomely slow (2 function calls) compared to other solutions
John Machin
+2  A: 
def unpack2rgb(intcol):
    tmp, blue= divmod(intcol, 256)
    tmp, green= divmod(tmp, 256)
    alpha, red= divmod(tmp, 256)
    return alpha, red, green, blue

If only the divmod(value, (divider1, divider2, divider3…)) suggestion was accepted, it would have simplified various time conversions too.

ΤΖΩΤΖΙΟΥ