我需要生成一个渐变位图,显示用户选择的两种颜色之间的彩虹渐变。生成彩虹很容易。下面的代码是我从Wiki获得的,并稍作修改。它的优点是快速和简单。
function TColor_Dialog.GiveRainbowColor (fraction: double): TAlphaColor;
var
m: Double;
r, g, b, mt: Byte;
begin
if fraction <= 0 then m := 0 else
if fraction >= 1 then m := 6
else m := fraction * 6;
mt := (round (frac (m) * $FF));
case Trunc (m) of
0: begin
R := $FF;
G := mt;
B := 0;
end;
1: begin
R := $FF - mt;
G := $FF;
B := 0;
end;
2: begin
R := 0;
G := $FF;
B := mt;
end;
3: begin
R := 0;
G := $FF - mt;
B := $FF;
end;
4: begin
R := mt;
G := 0;
B := $FF;
end;
5: begin
R := $FF;
G := 0;
B := $FF - mt;
end;
end; // case
Result := ColorToQuad (r, g, b);
end; // GiveRainbowColor //
这个算法的问题是它不能在两种颜色之间显示部分彩虹。好吧,当然可以,但你必须接近每种颜色的分数,我不喜欢那种解决方案。我尝试将颜色分解为其 r、g、b 通道,但这不起作用。事后看来,原因很明显。假设您需要 FF0000 和 0000FF 之间的渐变。你会有红色从 FF->00 和蓝色从 00->FF。但是,没有明显出现在彩虹渐变中的绿色 (00FF00)。
我需要的是一个渐变函数,我可以给出两种颜色和一个分数,它会生成一种颜色。谁能指出我的文章、算法甚至代码?
更新
NGLN 的答案是这个问题的正确答案。他和 Warren 都想知道当颜色不是亮色(包含 0、$FF 和值的颜色)时该怎么办。我尝试了几个角度:放大/缩小和 HSL 插值。我终于安顿下来了,因为最后一个是最简单的。
基本上你有两种颜色:from
和to
。使用 RGBtoHSL 从每种颜色中提取 HSL 参数:RGBtoHSL (col_from, hf, sf, lf)
. 接下来计算两种颜色之间的色调、饱和度和亮度并重建新颜色。这就是 NGLN 在他关于色调的更新中提到的,但如果你概括这个原则,你就会在任何颜色之间找到彩虹。
function TColor_Dialog.interpolate_hsl (col_from, col_to: TAlphaColor; fraction: double): TAlphaColor;
var af, at, ad: uInt8;
hf, ht, hd: single;
sf, st, sd: single;
lf, lt, ld: single;
begin
// Get each rgb color channel
af := GetAValue (col_from);
at := GetAValue (col_to);
RGBtoHSL (col_from, hf, sf, lf);
RGBtoHSL (col_to, ht, st, lt);
// Compute differences
ad := af + Round (fraction * (at - af));
hd := hf + fraction * (ht - hf);
sd := sf + fraction * (st - sf);
ld := lf + fraction * (lt - lf);
Result := MakeColor (HSLtoRGB (hd, sd, ld), ad);
end; // interpolate_hsl //
这为所有可能的颜色提供了彩虹。我对不透明度应用相同的插值,因此使用MakeColor
将插值的 Alpha 通道“摸索”到颜色中。