use*_*509 4 c# rgb colors color-management color-theory
我知道这已经被问过了,但那里给出的anwser不起作用.我花了一个多小时寻找一个公式或算法,但一无所获.结果,我开始编写自己的算法,以最有效的方式将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;
Run Code Online (Sandbox Code Playgroud)
如果我正在处理的颜色是原色,它可以正常工作,但在任何其他情况下都不行.什么会使它在任何地方都有效?我是否走在正确的轨道上?
我制作了一个算法,考虑了“白色”LED 的色温(因为这可能会根据灯带而变化 - 我的是暖白色,即 4500k)。要点在这里,代码在下面,还有更多上下文的博客文章哎呀!我的眼睛!Arduino WS2812B 设置和 RGBW 转换(柜灯第 3 部分)。
// Reference, currently set to 4500k white light:
// https://andi-siess.de/rgb-to-color-temperature/
const uint8_t kWhiteRedChannel = 255;
const uint8_t kWhiteGreenChannel = 219;
const uint8_t kWhiteBlueChannel = 186;
// The transformation has to be normalized to 255
static_assert(kWhiteRedChannel >= 255 ||
kWhiteGreenChannel >= 255 ||
kWhiteBlueChannel >= 255);
CRGBW GetRgbwFromRgb2(CRGB rgb) {
uint8_t r = rgb.r;
uint8_t g = rgb.g;
uint8_t b = rgb.b;
// These values are what the 'white' value would need to
// be to get the corresponding color value.
double whiteValueForRed = r * 255.0 / kWhiteRedChannel;
double whiteValueForGreen = g * 255.0 / kWhiteGreenChannel;
double whiteValueForBlue = b * 255.0 / kWhiteBlueChannel;
// Set the white value to the highest it can be for the given color
// (without over saturating any channel - thus the minimum of them).
double minWhiteValue = min(whiteValueForRed,
min(whiteValueForGreen,
whiteValueForBlue));
uint8_t Wo = (minWhiteValue <= 255 ? (uint8_t) minWhiteValue : 255);
// The rest of the channels will just be the original value minus the
// contribution by the white channel.
uint8_t Ro = (uint8_t)(r - minWhiteValue * kWhiteRedChannel / 255);
uint8_t Go = (uint8_t)(g - minWhiteValue * kWhiteGreenChannel / 255);
uint8_t Bo = (uint8_t)(b - minWhiteValue * kWhiteBlueChannel / 255);
return CRGBW(Ro, Go, Bo, Wo);
}
Run Code Online (Sandbox Code Playgroud)
我终于想出如何将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 };
Run Code Online (Sandbox Code Playgroud)
任何优化的想法都非常欢迎:)