2

I have using RUCKUS API for changing color of lamp and I need to convert color from RGB to XY to call an API.

I have tried this code:

1) Get the RGB values from your color object and convert them to be between 0 and 1

 function rgb_to_cie(red, green, blue)
    {
        //Apply a gamma correction to the RGB values, which makes the color more vivid and more the like the color displayed on the screen of your device
        var red     = (red > 0.04045) ? Math.pow((red + 0.055) / (1.0 + 0.055), 2.4) : (red / 12.92);
        var green   = (green > 0.04045) ? Math.pow((green + 0.055) / (1.0 + 0.055), 2.4) : (green / 12.92);
        var blue    = (blue > 0.04045) ? Math.pow((blue + 0.055) / (1.0 + 0.055), 2.4) : (blue / 12.92); 

        //RGB values to XYZ using the Wide RGB D65 conversion formula
        var X       = red * 0.664511 + green * 0.154324 + blue * 0.162028;
        var Y       = red * 0.283881 + green * 0.668433 + blue * 0.047685;
        var Z       = red * 0.000088 + green * 0.072310 + blue * 0.986039;

        //Calculate the xy values from the XYZ values
        var x       = (X / (X + Y + Z)).toFixed(4);
        var y       = (Y / (X + Y + Z)).toFixed(4);

        if (isNaN(x))
            x = 0;
        if (isNaN(y))
            y = 0;   
        return [x, y];
    }

but it didn't provide a proper solution.

SO if i pass r:182 g: 255 B: 65 as this then I got x as 22932 and y as 35249 (AS PER DOC OF API.)

How can I do that?

Harsh Patel
  • 6,334
  • 10
  • 40
  • 73
  • I assume that doc will tell you the range of X,Y. I would scale the values to that range. In fact x and y should be below 1 (often), but API probably want an integer. But you are requesting X,Y or x,y? And please do not call it CIE: CIE is CIE RGB, CIE XYZ, CIE xyz, CIE xyY, CIELAB, CIE LUV, etc. – Giacomo Catenazzi Feb 13 '19 at 09:32
  • @GiacomoCatenazzi Its X and Y.. Sorry for CIE I'll change. – Harsh Patel Feb 13 '19 at 09:57
  • Ah.. I was thinking about xy normalization (note, you return small x,y. But I didn't notice your transformation. The calculation assume red, green, and blue <= 1.0 (usually), but you are using values to 255. (see note in: https://en.wikipedia.org/wiki/SRGB#Specification_of_the_transformation) Your RGB (if you are using web colours, or screen values) are already gamma corrected. You should do the contrary function: get the linear R,G, B – Giacomo Catenazzi Feb 13 '19 at 10:04
  • Sorry to say but I didn't understand what you're trying to say. – Harsh Patel Feb 13 '19 at 10:10

2 Answers2

2

I got the solution and here I attached the answer if you're looing for,

let red = 100
let green = 100
let blue = 100

let redC =  (red / 255)
let greenC = (green / 255)
let blueC = (blue / 255)
console.log(redC, greenC , blueC)


let redN = (redC > 0.04045) ? Math.pow((redC + 0.055) / (1.0 + 0.055), 2.4): (redC / 12.92)
let greenN = (greenC > 0.04045) ? Math.pow((greenC + 0.055) / (1.0 + 0.055), 2.4) : (greenC / 12.92)
let blueN = (blueC > 0.04045) ? Math.pow((blueC + 0.055) / (1.0 + 0.055), 2.4) : (blueC / 12.92)
console.log(redN, greenN, blueN)

let X = redN * 0.664511 + greenN * 0.154324 + blueN * 0.162028;

let Y = redN * 0.283881 + greenN * 0.668433 + blueN * 0.047685;

let Z = redN * 0.000088 + greenN * 0.072310 + blueN * 0.986039;
console.log(X, Y, Z)

let x = X / (X + Y + Z);

let y = Y / (X + Y + Z);

X = x * 65536 
Y = y * 65536
Harsh Patel
  • 6,334
  • 10
  • 40
  • 73
  • Since that is accepted answer, can you explain your formulas a bit? – 18augst Nov 20 '22 at 01:37
  • @18augst Actually I got this formula from some documentation back then. Didn't remember as of now. – Harsh Patel Nov 28 '22 at 05:57
  • 1
    Ok, I've found an answer. In short: - normalize RGB color components - apply gamma correction - convert to `x`, `y`. [Here](https://gist.github.com/popcorn245/30afa0f98eea1c2fd34d) are more details. – 18augst Nov 29 '22 at 19:43
  • 1
    @18augst It is not a gamma correction, it's sRGB to Linear sRGB conversion. – secondplace Dec 17 '22 at 13:45
0

There are few errors:

First: You are using the normal transformation formula, where red, green, and blue should be in the range 0.0 to 1.0. So you may need to divide the values by 255.

Second: you are applying gamma. To transform to X,Y,Z you need linear values. Normally we have gamma corrected RGB (e.g. pixel values). So you are overcorrecting. Instead, you should apply the inverse of gamma, so that you will get the linear R,G,B, so that you can apply linear transformation to get X,Y,Z.

Third: you are returning x,y and not X,Y, as your question (and comment). On the other hand, are you sure you need X,Y? Often x,y are used for "colour". I would expect a x,y + Y (or some brightness parameter).

Possibly you should scale back the values. As you see, often the range is 0 to 1, or 0 to 100 (in past), or 0 to 255, 0 to 65535. There is no standard: these are just numbers without a unit. [Contrary to computer screens, a Phillips Hue should know what it is the maximum brightness, but .. this is an exception].

Giacomo Catenazzi
  • 8,519
  • 2
  • 24
  • 32
  • Thank you for the answer, I'll check the required value(that you told in three methods) in doc and revert back if I need more help. – Harsh Patel Feb 13 '19 at 10:48