我正在尝试控制一些RGB LED并从红色渐变为紫色。我正在使用HSV到RGB的转换,这样我就可以从色调0扫到色调300(除此之外它会向红色移动)。我注意到的问题是它似乎在光谱的青色和蓝色部分花了很长时间。所以我查看了HSV频谱的样子,发现了这个L
我没有意识到超过一半的光谱花费在绿色和蓝色之间。
但我真的希望它看起来更像这样:
与“标准”彩虹色相得益彰。 我想这会最终成为正常色调值的某种曲线,但我不确定如何计算该曲线。
在内部处理这种情况的实际HSV到RGB算法会很棒(任何代码都是真的,虽然它适用于Arduino)但是,即使只是解释我如何计算色调曲线也会非常感激。
答案 0 :(得分:2)
http://www.fourmilab.ch/documents/specrend/详细描述了如何将波长转换为CIE组件(大致对应于您眼中三种锥形传感器的输出),然后如何将这些转换为RGB值(警告某些波长在典型的RGB色域中 RGB等效物。)
或者:有各种“感知上均匀的颜色空间”,如CIE L * a * b *(参见例如http://en.wikipedia.org/wiki/Lab_color_space);你可以选择其中一个,沿着一条直线连接你在该空间中的起始和结束颜色,并转换为RGB。
但是,对于你的应用程序来说,这些中的任何一个都可能是过度的,并且没有明显的理由说明为什么它们应该更多 - 或者说 - 更好 - 比简单和纯粹的经验更好。那么为什么不这样做呢?
这完全是临时的,并没有任何关于它的原则,但它可能工作得很好,最终的代码基本上是微不足道的:
void compute_rgb(int * rp, int * gp, int * bp, int t) {
// t in the range 0..255 (for convenience)
int segment = t>>5; // 0..7
int delta = t&31;
int a=rgb_table[segment].r, b=rgb_table[segment+1].r;
*rp = a + ((delta*(b-a))>>5);
a=rgb_table[segment].g; b=rgb_table[segment+1].g;
*gp = a + ((delta*(b-a))>>5);
a=rgb_table[segment].b; b=rgb_table[segment+1].b;
*bp = a + ((delta*(b-a))>>5);
}
(如果你不关心保存每个可用周期,你可以使代码更清晰。)
对于它的价值,我的眼睛将分割点设置为大约(0),40,60,90,150,180,240,270,(300)的色调值。您的里程可能会有所不同。
答案 1 :(得分:1)
FastLED执行以下操作:https://github.com/FastLED/FastLED/wiki/FastLED-HSV-Colors
HSLUV是另一种选择:http://www.hsluv.org/。他们有多种不同语言的库。
此外,这是一种有趣的技术:https://www.shadertoy.com/view/4l2cDm
const float tau = acos(-1.)*2.;
void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
vec2 uv = fragCoord.xy / iResolution.xy;
vec3 rainbow = sqrt( //gamma
sin( (uv.x+vec3(0,2,1)/3.)*tau ) * .5 + .5
);
fragColor.rgb = rainbow;
}
另请参阅: https://en.wikipedia.org/wiki/Rainbow#Number_of_colours_in_spectrum_or_rainbow了解更多信息。