user2950509 - 1 year ago 109

C# Question

I know this has already been asked, but the anwser given there doesn't work. I've spent over an hour looking for a formula or algorithm, but have found nothing. As a result, I've started writing my own algorithm to convert RGB to RGBW in the most efficient way possible. This is what I've currently got:

`//'Ri', 'Gi', and 'Bi' correspond to the Red, Green, and Blue inputs.`

var M = Math.Max(Ri, Math.Max(Gi, Bi)); //The maximum value between R,G, and B.

int Wo =0; //White output

int Ro=0; //Red output

int Go=0; //Green output

int Bo=0; //Blue output

int av = 0; //Average between the two minimum values

int hR = 0; //Red with 100% hue

int hG = 0; //Green with 100% hue

int hB = 0; //Blue with 100% hue

//These 4 lines serve to figure out what the input color is with 100% hue.

float multiplier = 255.0f / M;

hR = Convert.ToInt32(Ri * multiplier);

hG = Convert.ToInt32(Gi * multiplier);

hB = Convert.ToInt32(Bi * multiplier);

//Depending on the maximum value, get an average of the least used colors, weighted for their importance in the overall hue.

//This is the problematic part

if (M == Ri)

av = (Bi*hB + Gi*hG) / (hB+hG);

else if (M == Gi)

av = (Ri*hR + Bi*hB) / (hR+hB);

else if (M == Bi)

av = (Gi*hG + Ri*hR) / (hG+hR);

//Set the rgbw colors

Wo = av;

Bo = Bi - av;

Ro = Ri - av;

Go = Gi - av;

if (Wo < 1) Wo = 0;

if (Bo < 1) Bo = 0;

if (Ro < 1) Ro = 0;

if (Go < 1) Go = 0;

if (Wo > 255) Wo = 255;

if (Bo > 255) Bo = 255;

if (Ro > 255) Ro = 255;

if (Go > 255) Go = 255;

It works fine if the color I'm dealing with is a primary color, but not in any other case. What would make it work everywhere? Am I even on the right track?

EDIT: Here's a .gif of the issue I'm running into. the RGBW values are all the way at the bottom

Answer Source

I've finally figured out how to convert RGB to RGBW, turns out my previous method was completely wrong:

```
//Get the maximum between R, G, and B
float tM = Math.Max(Ri, Math.Max(Gi, Bi));
//If the maximum value is 0, immediately return pure black.
if(tM == 0)
{ return new rgbwcolor() { r = 0, g = 0, b = 0, w = 0 }; }
//This section serves to figure out what the color with 100% hue is
float multiplier = 255.0f / tM;
float hR = Ri * multiplier;
float hG = Gi * multiplier;
float hB = Bi * multiplier;
//This calculates the Whiteness (not strictly speaking Luminance) of the color
float M = Math.Max(hR, Math.Max(hG, hB));
float m = Math.Min(hR, Math.Min(hG, hB));
float Luminance = ((M + m) / 2.0f - 127.5f) * (255.0f/127.5f) / multiplier;
//Calculate the output values
int Wo = Convert.ToInt32(Luminance);
int Bo = Convert.ToInt32(Bi - Luminance);
int Ro = Convert.ToInt32(Ri - Luminance);
int Go = Convert.ToInt32(Gi - Luminance);
//Trim them so that they are all between 0 and 255
if (Wo < 0) Wo = 0;
if (Bo < 0) Bo = 0;
if (Ro < 0) Ro = 0;
if (Go < 0) Go = 0;
if (Wo > 255) Wo = 255;
if (Bo > 255) Bo = 255;
if (Ro > 255) Ro = 255;
if (Go > 255) Go = 255;
return new rgbwcolor() { r = Ro, g = Go, b = Bo, w = Wo };
```

Any optimization ideas are more than welcome :)