Convert a RGB colour value to Decimal

20,794

Solution 1

RGB integers are typically treated as three distinct bytes where the left-most (highest-order) byte is red, the middle byte is green and the right-most (lowest-order) byte is blue. You can retrieve the values of these individual bytes like this:

var c = 0xff03c0; // 16712640
var components = {
    r: (c & 0xff0000) >> 16, 
    g: (c & 0x00ff00) >> 8, 
    b: (c & 0x0000ff)
};

You can re-create a color from its components by shifting the bytes back in:

c = (components.r << 16) + (components.g << 8) + (components.b);

In your case, simply substitute components.r (etc) with your actual variables.

Solution 2

A much better answer (in terms of clarity) is this:

'Convert RGB to LONG:
 LONG = B * 65536 + G * 256 + R

'Convert LONG to RGB:
 B = LONG \ 65536
 G = (LONG - B * 65536) \ 256
 R = LONG - B * 65536 - G * 256

LONG is your long integer (decimal) that you want to make. Easy huh? Sure, bitshift

Solution 3

var dec = (b & 0xff) << 16 + (g & 0xff) << 8 + (r & 0xff);

(I think that's the correct order for the r,g,b values)

Update

I just checked for browser applications and I got the order wrong, so the correct formula for browsers (read HTML+CSS+javascript) is:

var dec = r << 16 + g << 16 + b;

Assuming r,g,b values <= 255

Other API's may expect a different order for the r,g,b values. I seem to remember at least one that has the order reversed (per my original answer), but I think which one it is at the moment.

Solution 4

if (color.substr(0, 1) === '#') {
    return color;
}
var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color);
var red = parseInt(digits[2]);
var green = parseInt(digits[3]);
var blue = parseInt(digits[4]);
var rgb = blue | (green << 8) | (red << 16);
return rgb.toString(10);

Solution 5

I agree that bitshift is clearer and probably better performance.

That said, if you want a math answer due to language support (such as doing this in a spreadsheet) modulus % and trunc() or floor() make it simple:

Assuming 8 bit values for red green and blue of course (0-255):

var rgbTotal = red * 65536 + green * 256 + blue;

var R = Math.trunc( rgbTotal / 65536 );
var G = Math.trunc( ( rgbTotal % 65536 ) / 256 );
var B = rgbTotal % 256;

Discussion: Pointing to sam's answer, RGB values are nearly always big endian in terms of order, certainly on webpages, jpeg, and png. Personally I think it's best to multiply red by 65536 instead of blue, unless you're working with a library that requires it otherwise.

To return to separate values:

  • For R, just divide by 65536 and truncate the remainder.
  • For G, we discard R via mod 65536 then dividing by 256, truncating the remainder (remainder is blue).
  • For B, we take mod 256, which disposes of the two higher bytes.

For R & G the number needs to be truncated to discard the remainder, language specific, mainly we want the integer. In javascript Math.trunc() is the easy way, and Math.floor() also works. It's not needed for B as that IS the remainder from the modulus — however this also assumes that we don't need error checking such as from user input, i.e. the value for B is always an integer 0-255.

Share:
20,794
sazr
Author by

sazr

Updated on July 09, 2022

Comments

  • sazr
    sazr almost 2 years

    How do I convert a RGB colour value to just plain decimal?

    So I have: RGB(255,255,255) is white
    Its decimal equivalent is: 16777215

    I have tried thinking it might just be:

    var dec = r*g*b; // but this doesn't work
    

    Although that doesn't work.

    Anyone know of the algorithm/equation to convert from RGB (or rgba) to decimal?

  • Martin James
    Martin James over 12 years
    You may well be right about the order, in which case, my answer is wrong :(
  • Nicol Bolas
    Nicol Bolas over 12 years
    The correct order in terms of what? For who? The order depends on who's reading the value.
  • Andrew Cooper
    Andrew Cooper over 12 years
    @Nicol - No, the correct order depends on the API. I'm not sure about the Win32 API, but for browser based applications (which I assume is being addressed here) I'm pretty sure that Blue is the high-order byte (of the three) and Red is the low-order byte.
  • sazr
    sazr over 12 years
    seem to be getting the wrong colours, are you sure thats the right order?
  • Wayne
    Wayne over 12 years
    If those variables just hold individual color components, then there's really no point to the bit-masks.
  • Andrew Cooper
    Andrew Cooper over 12 years
    @Jake - Not 100%, no. Try swapping r and b.
  • Andrew Cooper
    Andrew Cooper over 12 years
    @lwburk - True. The bit-masks are there for safety in case the individual variables contain values > 255 for some reason. You could also do max(r, 255) if you want to clip the value rather than mask it (which may be more appropriate for some applications).
  • Wayne
    Wayne over 12 years
    @AndrewCooper - Right, because if they do contain values greater than 255, then the mask is going to create effects that were almost certainly un-expected/wanted. It should probably just be treated as an error in that case.
  • Andrew Cooper
    Andrew Cooper over 12 years
    @Martin James - Nope. Your answer is correct. See my update.
  • sharon_antony
    sharon_antony over 11 years
    rgb.toString(10) is what needed
  • John Bingham
    John Bingham almost 8 years
    @DanielA.White may not think so, but I cannot see how any other answer to this question is half as clear as this one. Even I can I understand this.
  • Wayne
    Wayne about 5 years
    This only appears easier to someone who doesn't know bit manipulation in the same way that a bad answer in English appears to be better than a good answer in French to somebody who doesn't read French. Learn bit manipulation and you learn the generalizable principles that make my answer much clearer in the long run.
  • vorwerg-ni
    vorwerg-ni over 3 years
    actually its: LONG = R * 65536 + G * 256 + B (you mixed up B and R) see rapidtables.com/web/color/RGB_Color.html