How to convert HSB to RGB

2019-02-20 17:09发布

问题:

I having one Delphi XE2 Project to change Label01 Font Color using Timer04. So I have written the following codes:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  Timer04.Enabled := true;
end;
..
..
..
..
..
procedure TMainForm.Timer04Timer(Sender: TObject);
var
  StartColor, RedColor, GreenColor, BlueColor: integer;
begin
  StartColor := ColorToRGB(Label01.Font.Color);
  RedColor := GetRValue(StartColor);
  GreenColor := GetGValue(StartColor);
  BlueColor := GetBValue(StartColor);
  if RedColor <= 251 then Inc(RedColor, 1) else RedColor := 1;
  if GreenColor <= 252 then Inc(GreenColor, 2) else GreenColor := 2;
  if BlueColor <= 253 then Inc(BlueColor, 3) else BlueColor := 3;
  Label01.Font.Color := RGB(RedColor, GreenColor, BlueColor);
end;

This codes work perfectly. Label01 Font Color changes between different colors.

Now I am trying to implement that Label02 Color will be fixed (say Green) and the value of brightnees will be increase from 0 to 100. If the value reaches to 100 it will be decreased to 0 and it will be continuous to a loop.

For my case I have chosen HUE=135, SATURATION=85 and BRIGHTNESS=50. The value of BRIGHTNESS will be increased from 50 to 100 and then will be decreased from 100 to 0 and it will be continued. But the problem is that there is no such Function available to convert HSB to RGB and vice versa in Delphi XE2. I have Gooled it. But I have found any Function as HSBToRGB. Only some Delphi Unit is availabe. I have read their revoews and found that every one is having some bugs.

回答1:

Here is a Delphi a translation of C code found here: http://www.cs.rit.edu/~ncs/color/t_convert.html

function RGBFP(R, G, B: Double): TColor;
const
  RGBmax = 255;
begin
  Result := RGB(Round(RGBmax * R), Round(RGBmax * G), Round(RGBmax * B));
end;

function HSVtoRGB(H, S, V: Double): TColor;
var
  i: Integer;
  f, p, q, t: Double;
begin
  Assert(InRange(H, 0.0, 1.0));
  Assert(InRange(S, 0.0, 1.0));
  Assert(InRange(V, 0.0, 1.0));

  if S = 0.0 then
  begin
    // achromatic (grey)
    Result := RGBFP(V, V, V);
    exit;
  end;

  H := H * 6.0; // sector 0 to 5
  i := floor(H);
  f := H - i; // fractional part of H
  p := V * (1.0 - S);
  q := V * (1.0 - S * f);
  t := V * (1.0 - S * (1.0 - f));
  case i of
  0:
    Result := RGBFP(V, t, p);
  1:
    Result := RGBFP(q, V, p);
  2:
    Result := RGBFP(p, V, t);
  3:
    Result := RGBFP(p, q, V);
  4:
    Result := RGBFP(t, p, V);
  else
    Result := RGBFP(V, p, q);
  end;
end;

I've given this minimal testing. Please do feel free to double check it.



回答2:

For Firemonkey it's HSLtoRGB from System.UIConsts.pas It's similar to HSB (=HSV). All you can do with HSB you can do with HSL

function HSLtoRGB(H, S, L: Single): TAlphaColor;

It returns FMX TAlphaColor - that is RGB. For VCL you need TColor, that is BGR.

So use RGBtoBGR in the same unit.

function RGBtoBGR(const C: TAlphaColor): TAlphaColor;

Then just do Color := TColor(MyAlphaColorVariable);

AFAIK there is no HSB function in standard units.