What would be the best way to change RGB values to RGB+Y values?
We have a new led light with and extra Y led to compensate for poor display of yellows and oranges with the regular RGB module.

Hi Alex,

My first thought is you could store the Y value in the alpha channel of an RGBA image. Might require a bit of low-level bit-fiddling, but not inherently difficult.


What I was looking for was a way of converting the RGB values to RGBY.
The same way you would convert RGB to CMYK

[quote author=“alexbeim”]What I was looking for is a way of converting the RGB values to RGBY.
The same way you would convert RGB to CMYK[/quote]

Ah. Well if Y is luminance, then something in a loop like this would do the trick (if you do it in OpenCV:

void rgb2rgby(IplImage *img_src, IplImage *img_dst)  
   for(int i = 0; i  < img_src->height; i++)  
      uchar *p_row_src = (uchar*)(img_src->imageData + i*img_src->widthStep);  
      uchar *p_row_dst = (uchar*)(img_dst->imageData + i*img_dst->widthStep);  
      for(int j = 0; j < img_src->width, j++)  
         uchar Y = (uchar)CLAMP(0.3*p_row_src[0] + 0.59*p_row_src[1] + 0.11*p_row_src[0], 0, 255);  
         *p_row_dst++ = *p_row_src++  
         *p_row_dst++ = *p_row_src++  
         *p_row_dst++ = *p_row_src++  
         *p_row_dst++ = Y;  

uchar is just a typedef for unsigned char.

OpenCV’s native channel ordering is BGR, so you’ll have to reverse the order of the coefficients in the luminance calculation if you loaded the image from OpenCV.

Hope that’s what you were after.


My intuition says: compute the distance from your color to each other primary color in RGB space, then multiply the RGBY representation of those colors by the distance.

So, color/RGB/RGBY:

R <1, 0, 0> <1, 0, 0, 0>
G <0, 1, 0> <0, 1, 0, 0>
B <0, 0, 1> <0, 0, 1, 0>
Y <1, 1, 0> <0, 0, 0, 1>

Let’s say you want to convert color C = <.1, .2., .3>

C to R = .97
C to G = .86
C to B = .73
C to Y = 1.24

Then normalize everything by sqrt(3), the maximum distance between R, G, B or Y to some color C:

R = .55
G = .50
B = .42
Y = .71

And then take the inverse (i.e., 1 - x), so you get “similarity” rather than “difference/distance”:

R = .45
G = .50
B = .58
Y = .29

Since the RGBY vectors all have only one 1 and are 0 otherwise, we can multiply + add them by just substituting the values:

<.1, .2, .3> in RGB = <.45, .50, .58, .29> in RGBY

There’s definitely something wrong with this idea, because it doesn’t compute RGB to RGB correctly… but something along these lines might work.

there’s probably not going to be any particular mathematical solution to this, because without calibrating things with the physical device, there’s no way of knowing how much yellow you have to turn on.

but, along the lines of what Kyle suggested, although simpler: calculate the distance away from <1,1,0> (maybe just using the R and G components, so simplifies to the distance away from <1,1>, invert, and send that to Y.

I considered that, but I think the operation needs to be done on all the colors rather than just generating Y – otherwise you will get overly yellow colors (i.e., you will be duplicating the yellow component).

There is definitely some calibration that needs to be done. I’ve done some experiments recently using a webcam-for-calibration that might prove helpful if you’re trying to match an LED to an on screen color.

Also, in my experience with RGB LEDs: you really can generate most colors, you just need to make sure it’s diffused well or you get an effect of having different colors in different places.

yeah - although as i understood it, the point of the extra Y LED just is to make things overly yellow - or rather, compensate for the lack of yellow in the base lights. (seems weird, because in me experience it’s blue you’ve got to boost, not yellow… well anyway…)

I found this info from a past discussion on the topic:

You want RGB to RGBY? Since Y is a combination of R and G, you could
just use an undercolor removal algorithm that removes yellow instead of
black. You don’t say *which* yellow, so I’ll assume the yellow that is
equal R and G.

Y = (R - min(R,G)) + (G - min(R,G));
R -= min(R,G);
G -= min(R,G);

Any opinions on this solution?

That looks a lot more reasonable :slight_smile: I think under color removal is generally used in subtractive situations rather than additive ones, but it looks like the same principle should apply here.

And if, like Damian says, you’re really just looking for brighter yellows, you can add a “compensation” variable:

cpmp = 0;  
min = min(R,G)  
Y = (R - min) + (G - min);  
R -= min * comp;  
G -= min * comp;  

When comp = 0, yellows are just “doubled”; and when comp = 1 all yellows are removed from RG and placed on Y (which should result in the same color).