计算渐变颜色的最快方法?

问题描述 投票:8回答:3

我正在收集一小部分与渐变相关的类型/函数,以备将来使用。我想确保至少有两个过程:ColorBetween和ColorsBetween。我可能只想获取任意2种颜色(ColorsBetween)之间的TColor数组,并且我可能还只需要知道一种颜色值,即两种颜色之间的百分比(ColorBetween)。

我已经在下面完成了大部分工作。除此之外,我有两个核心问题:

  1. 如何计算给定百分比的每个RGB通道的中间颜色? (请参见下面我有[???]的位置)
  2. 完成我正在做的事情的最快方法是什么(同时保留两个不同的功能)?

这里是代码:

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  StrUtils, StdCtrls, Math;

type
  TColorArray = array of TColor;

implementation

function ColorsBetween(const ColorA, ColorB: TColor; const Count: Integer): TColorArray;
var
  X: Integer; //Loop counter
begin
  SetLength(Result, Count);
  for X:= 0 to Count - 1 do 
    Result[X]:= ColorBetween(ColorA, ColorB, Round((X / Count) * 100)); //Correct?
end;

function ColorBetween(const ColorA, ColorB: TColor; const Percent: Single): TColor;
var
  R1, G1, B1: Byte;
  R2, G2, B2: Byte;
begin
  R1:= GetRValue(ColorA);
  G1:= GetGValue(ColorA);
  B1:= GetBValue(ColorA);
  R2:= GetRValue(ColorB);
  G2:= GetGValue(ColorB);
  B2:= GetBValue(ColorB);
  Result:= RGB(
    EnsureRange(([???]), 0, 255),
    EnsureRange(([???]), 0, 255),
    EnsureRange(([???]), 0, 255)
  );
end;

编辑:Percent: Integer更改为Percent: Single可获得更平滑的效果-不限于100个可能的值。

delphi graphics colors delphi-7 gradient
3个回答
7
投票

听起来您想替换您的???与

Round((R1*Percent + R2*(100-Percent))/100.0)

不需要代码中的EnsureRange,因为只要Percent的范围为0到100,此函数必须返回0到255的值。我想我会将EnsureRange应用于Percent (将其设置为0.0到100.0),然后使用以下代码:

Result := RGB(
  Round((R1*Percent + R2*(100-Percent))/100.0),
  Round((G1*Percent + G2*(100-Percent))/100.0),
  Round((B1*Percent + B2*(100-Percent))/100.0),
);

您的第一个函数返回一个数组,其第一个颜色为ColorA。也许您会对此更好:

for X:= 0 to Count - 1 do
  Result[X]:= ColorBetween(ColorA, ColorB, (X+1) / (Count+1) * 100.0);

这在数组的两端给出相同的行为。或者,也许您想同时包含ColorAColorB。然后,您将使用:

X / (Count-1) * 100.0

但是如果您这样做,请记住Count必须大于1,否则您将被零除。从来没有解决过!


不用担心性能。毫无疑问,可以使代码稍快一些,但是肯定不会成为瓶颈。您将采用这些颜色并与它们一起绘制。与这些简单的例程相比,这将消耗更多的资源。


最后一点。 RGB空间中的插值在人眼看来不会特别平滑或线性。使用浮点百分比不能逃避这个事实。为了在查看时获得最佳结果,您需要在不同的色彩空间中进行插值。


4
投票

我不知道这是否是最快的方法,但是它可以工作:

function ColorBetween(const ColorA, ColorB: TColor; const Percent: Integer): TColor;
var
  R1, G1, B1: Byte;
  R2, G2, B2: Byte;
begin
  R1:= GetRValue(ColorA);
  G1:= GetGValue(ColorA);
  B1:= GetBValue(ColorA);
  R2:= GetRValue(ColorB);
  G2:= GetGValue(ColorB);
  B2:= GetBValue(ColorB);

  Result:= RGB(
    Percent * (R2-R1) div 100 + R1,
    Percent * (G2-G1) div 100 + G1,
    Percent * (B2-B1) div 100 + B1
  );
end;

function ColorsBetween(const ColorA, ColorB: TColor; const Count: Integer): TColorArray;
var
  X : integer;
begin
  SetLength(Result, Count);
  for X := 0 to Count - 1 do
    Result[X] := ColorBetween(ColorA, ColorB, Round((X / (Count-1)) * 100));  //Note: Divide by count-1
end;

0
投票

如何从该函数调用数组?

© www.soinside.com 2019 - 2024. All rights reserved.