2016-10-28 10 views
2

Я знаю это has already been asked, но anwser данный там не работает. Я потратил более часа на поиски формулы или алгоритма, но ничего не нашел. В результате я начал писать свой собственный алгоритм для конвертирования RGB в RGBW самым эффективным способом. Это то, что я в настоящее время есть:Преобразование RGB в RGBW

 //'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; 

Он отлично работает, если цвет, который я имею дело с является основной цвет, но не в любом другом случае. Что заставило бы его работать везде? Я даже на правильном пути?

РЕДАКТИРОВАТЬ: Вот. Проблема с проблемой, с которой я сталкиваюсь. значения RGBW всех путей в нижнем enter image description here

+2

Интересно, являются ли ваши целые деления частью проблемы. Разве вы не хотите, чтобы множитель был float/decimal и усекался/округлял конечные значения? – shawnt00

+1

Что значит «не работает»? –

+0

@ shawnt00 Я так не думаю.Я уверен, что .NET это с этим справляется. Я получаю тот же результат, делясь на парные или плавающие, а затем конвертируя в целое число, но я получаю то же самое. – user2950509

ответ

4

Я наконец-то понял, как конвертировать RGB в RGBW, получается, что мой предыдущий метод был полностью неверно:

//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 }; 

enter image description here

Любые идеи оптимизации более чем приветствуется :)

1

Я думаю, что проблема здесь:

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); 

Вы делаете целые подразделения здесь. Все ваши переменные являются целыми числами, поэтому деление будет целочисленным.

if (M == Ri) 
     av = (int)((float)(Bi*hB + Gi*hG)/(hB+hG)); 
    else if (M == Gi) 
     av = (int)((float)(Ri*hR + Bi*hB)/(hR+hB)); 
    else if (M == Bi) 
     av = (int)((float)(Gi*hG + Ri*hR)/(hG+hR)); 

Это будет разделение с плавающей запятой и даст вам ответ, который вам нужен. Вы все еще можете обнаружить, что у вас есть ошибки округления - в этом случае измените float на double.

Изменение расчета мультипликатора плавать:

float multiplier = 255.0/M; 

только адресованный половину вопроса, но теперь вызывает другое осложнение, как ваши тесты:

if (M == Ri) 
else if (M == Gi) 
else if (M == Bi) 

теперь вряд ли когда-либо быть правдой. Вам нужно будет добавить коэффициент округления в тест.

if (Math.Abs(M - Ri) < epsilon) 
else if (Math.Abs(M - Gi) < epsilon) 
else if (Math.Abs(M - Bi) < epsilon) 

epsilon, где это подходит малое значение (обычно я хотел бы предложить 10e-6, но вы можете экспериментировать.

Кроме того, если M не достаточно близко к любому из RGB значения, которые дон 't set av - он всегда остается равным нулю. Это также даст вам результат, когда вы видите, где все черное

+0

Исправлено, и до сих пор ничего. Я уверен, что проблема исходит из реальной логики, которую я использую. Если вы посмотрите на то, что происходит, когда я пытаюсь насытить/удалить насыщение бирюзы, у меня есть белый выход 255, когда он должен быть 0 (В полностью насыщенном бирюзовом нет белого цвета). Это должно вести себя, как когда я насыщаю/де-насыщаю синий. – user2950509

0

Я мог бы быть немного не здесь, а в качестве инженера электроники я вижу светодиоды outputing свет, а затем код XD. В любом случае вывод белого может быть сделан путем «освещения» всех каналов rgb или белого цвета, но с той же интенсивностью (и благополучия светодиодов с моей точки зрения) все 4 канала могут быть смешаны для вывода того же белого цвета, что и белый перегруженный белый канал. Я сомневаюсь, что это проблема на данный момент, но это может быть полезно позже.

+0

Однако, если у меня есть очень высокий CRI белый светодиод, будет ли канал RGB полностью не ухудшать качество света? – user2950509