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.
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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.
Method 2
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.
Method 3
>>> import struct
>>> str='aabbcc'
>>> struct.unpack('BBB',str.decode('hex'))
(170, 187, 204)
for python3:
>>> struct.unpack('BBB', bytes.fromhex(str))
and
>>> rgb = (50,100,150)
>>> struct.pack('BBB',*rgb).encode('hex')
'326496'
for python3:
>>> bytes.hex(struct.pack('BBB',*rgb))
Method 4
>>> r, g, b = (111, 121, 131)
>>> packed = int('%02x%02x%02x' % (r, g, b), 16)
This produces the following integer:
>>> packed 7305603
You can then unpack it either the long explicit way:
>>> packed % 256 255 >>> (packed / 256) % 256 131 >>> (packed / 256 / 256) % 256 121 >>> (packed / 256 / 256 / 256) % 256 111
..or in a more compact manner:
>>> b, g, r = [(packed >> (8*i)) & 255 for i in range(3)] >>> r, g, b
Sample applies with any number of digits, e.g an RGBA colour:
>>> packed = int('%02x%02x%02x%02x' % (111, 121, 131, 141), 16)
>>> [(packed >> (8*i)) & 255 for i in range(4)]
[141, 131, 121, 111]
Method 5
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)
Method 6
Just a note for anyone using Google’s Appengine Images Python API. I found I had a situation where I had to supply a method with a 32-bit RGB color value.
Specifically, if you’re using the API to convert a PNG (or any image with transparent pixels), you’ll need to supply the execute_transforms method with an argument called transparent_substitution_rgb which has to be a 32-bit RGB color value.
Borrowing from dbr’s answer, I came up with a method similar to this:
def RGBTo32bitInt(r, g, b):
return int('%02x%02x%02x' % (r, g, b), 16)
transformed_image = image.execute_transforms(output_encoding=images.JPEG, transparent_substitution_rgb=RGBTo32bitInt(255, 127, 0))
Method 7
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.
Method 8
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].
Method 9
If you are using NumPy and you have an array of RGBints, you can also just change its dtype to extract the red, green, blue and alpha components:
>>> type(rgbints)
numpy.ndarray
>>> rgbints.shape
(1024L, 768L)
>>> rgbints.dtype
dtype('int32')
>>> rgbints.dtype = dtype('4uint8')
>>> rgbints.shape
(1024L, 768L, 4L)
>>> rgbints.dtype
dtype('uint8')
Method 10
def int2color(red,green,blue):
def chex(c):
if c < 16:
return "0"+hex(c)[2:]
else:
return hex(c)[2:]
return "#{}{}{}".format(chex(red),chex(green),chex(blue))
>>> int2color(49, 105, 0)
#316900
Method 11
Adding to what is mentioned above. A concise one-liner alternative.
# 2003199 or #E190FF is Dodger Blue. tuple((2003199 >> Val) & 255 for Val in (16, 8, 0)) # (30, 144, 255)
And to avoid any confusion in the future.
from collections import namedtuple
RGB = namedtuple('RGB', ('Red', 'Green', 'Blue'))
rgb_integer = 16766720 # Or #ffd700 is Gold.
# The unpacking asterisk prevents a TypeError caused by missing arguments.
RGB(*((rgb_integer >> Val) & 255 for Val in (16, 8, 0)))
# RGB(Red=255, Green=215, Blue=0)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0