2016-10-28 165 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; 

它工作正常,如果我處理的顏色是原色,但不是在任何其他情況下。什麼使它在任何地方都能工作?我是否在正確的軌道上?

編輯:這是我遇到的問題.gif。在RGBW值一路底部 enter image description here

+2

我不知道你的整數部分是否是問題的一部分。你不想讓這個倍數成爲浮點數/小數點並截斷/舍入最終值嗎? – 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設置av - 它總是保持爲零,這也會給你看到所有東西都是黑色的結果

+0

已修復,仍然沒有。我很確定這個問題來自我正在使用的實際邏輯。如果你看看當我嘗試飽和/去飽和綠松石時會發生什麼,當它應該是0時,我得到了255的白色輸出(完全飽和的綠松石中沒有白色)。它應該表現得像我飽和/去飽和藍色時一樣。 – user2950509

0

我可能是有點過這裏,但作爲一名電子工程師我看到的LED outputing光,然後代碼XD。無論如何,輸出白色可以通過「點亮」所有RGB或白色通道來完成,但保持相同的強度(以及從我的角度來看LED的良好狀態),所有4個通道可以混合以輸出與過度驅動的白色相同的白色渠道。 我懷疑這是什麼問題,但稍後可能會有所幫助。

+0

但是,如果我有一個非常高的CRI白光LED,那麼RGB通道會不會損壞光的質量? – user2950509