Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting an RGBW color to a standard RGB/HSB representation

I am building an interface for light management in a home automation system. I managed to control standard on/off and dimmable light for various providers with little problem, but now I am stuck with a problem related to RGB light.

The light I am currently using is an RGBW led strip - specifically, I am working with a low-cost RGBW light: the light is composed by four led and every led can be controlled individually.

To be more clear - I am working on some c# code that should retrieve the currently selected color and display it in the UI, and enable the user to specify a new color for the light. For setting the color and retrieving it I must use a command provider that enables me to send and receive commands via a web service.

The provider works with RGBW colors - the four component for Red, Green, Blue and White are used. To represent the current light color on my interface I would like to translate the RGBW color returned by the service to a more standard RGB/HSB scheme.

Searching the web, the only reference for color conversion that I found (excluding a c++ sample for rgb to rgbw conversion that, based on my understanding, must have some severe bug) is this article that shows a conversion from HSI to RGBW, which is the inverse of what I needed: link here

I am searching for some insight about how I can achieve this conversion (or a simple explanation of why it isn't possible). As far as I get the conversion from RGB to an RGBW is arbitrary - a single RGB value can be represented as multiple RGBW values, but the opposite conversion should be univocal. Also note that while I am using c#, feel free to refer to algorithms in other language too - language isn't the problem, the problem is that I don't know the math to do the color conversion.

like image 410
SPArcheon Avatar asked Jan 14 '14 15:01

SPArcheon


2 Answers

How to convert RGB to RGBW is described in item 2.1 of the following paper

http://www.mirlab.org/conference_papers/International_Conference/ICASSP%202014/papers/p1214-lee.pdf

Think of your leds as a huge pixel. Oliver's answer uses Wo = min(Ri,Gi,Bi), what is computationaly cheap and just works. This paper explains other alternatives to minimize power consumption, what is good for a home automation project. I'm also on a home automation project with OpenHAB, Arduino and RGBW leds and on the one hand paper proposed alternative would be good, on the other hand a huge LUT would just not work and convert all values on arduino eighter. I would suggest you to try correcting RGB values using not so energy eficient technics as cited in the paper:

Assuming Ri, Gi, Bi are color inputs, integers from 0 to 255, so Q = 255 and that your outputs are Wo, Ro, Go and Bo with values from 0 to 255:

M = max(Ri,Gi,Bi)
m = min(Ri,Gi,Bi)

Wo = if (m/M < 0.5) use ( (m*M) / (M-m) ) else M 
Q = 255
K = (Wo + M) / m
Ro = floor( [ ( K * Ri ) - Wo ] / Q )
Go = floor( [ ( K * Gi ) - Wo ] / Q )
Bo = floor( [ ( K * Bi ) - Wo ] / Q )

Exercise it in a spreadsheet before implementing, experiment on Wo = m, m^2 and -m^3+m^2+m, correct Wo value with the right Qw and you will be surprised that the simple solution without correction is not what one would expect and that other answers do not vary that much. Check the paper for color distortion results, I suppose that if you do not correct RGB values you will end up with some washed out colors.

like image 135
Roberto Cantanhede Avatar answered Sep 30 '22 10:09

Roberto Cantanhede


I have been reviewing the answer suggested by Roberto but the colors seemed dimmer and undersaturated in many cases. Taking the example of RGB = (255,255,2) leads to RGBW = (128,128,1,2).

Digging further, it seems that the paper by Chul Lee has an error in its equation for K. The equation, which comes from a paper by Lili Wang ("Trade-off between luminance and color in RGBW displays for mobile-phone usage") is actually:

K = (Wo + M)/M

Note that it is a capital M, not a lowercase m. Given this change, you also do not need Q since it scales properly by nature. Using the new K on the same RGB = (255,255,2) example leads to a much more reasonable RGBW = (255,255,0,2).

Putting it all together:

M = max(Ri,Gi,Bi)
m = min(Ri,Gi,Bi)

Wo = if (m/M < 0.5) use ( (m*M) / (M-m) ) else M 
K = (Wo + M) / M
Ro = floor[ ( K * Ri ) - Wo ]
Go = floor[ ( K * Gi ) - Wo ]
Bo = floor[ ( K * Bi ) - Wo ]
like image 24
cobra18t Avatar answered Sep 30 '22 09:09

cobra18t