如何避免转换时的变量近似?

时间:2013-07-26 19:06:53

标签: delphi

我有一个Delphi XE2项目。在我的项目中,我有MainFormLabel01Label02Label03Label04Label05Label06,{ {1}},Edit01Edit02Edit03Edit04BitBtn01BitBtn02Timer01

我正在尝试实施以下内容:

Timer02 Button Click之后,Brightness的{​​{1}}将会持续增加或减少,就像'微软已完成在任务栏中的Windows 7中的任何工作后完成此操作'一样。

所以我的逻辑是:在Label01.Font.Color上,根据名为BitBtn01.Click的程序,Label01.Font.Color将被转换为HSB Color Model。如果RGBToHSV小于100%,则会增加Brightness。达到Timer01达到100%后,它将递减Brightness达25%。每当Timer02根据名为Brightness的程序更新Label01.Font.ColorHSVToRGVHue保持不变。这些程序根据Saturation工作。

根据我的要求,我写了以下代码:

Color Conversion Algorithm

所需的链接如下:

  1. HSVToRGB程序 - hxxp://www.delphipages.com/forum/showthread.php?t = 133111

  2. RGBToHSV程序 - hxxp://www.delphipages.com/forum/showthread.php?t = 133111

  3. 颜色转换算法 - hxxp://www.cs.rit.edu/~ncs/color/t_convert.html

  4. 将'x'替换为't'。

    Here is the download link of my project

    我的编码是正确的,编译得很完美。

    但问题是,在运行程序几次后,unit ApplicationWizard01; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Buttons, Math; type TMainForm = class(TForm) BitBtn01: TBitBtn; BitBtn02: TBitBtn; Edit01: TEdit; Edit02: TEdit; Edit03: TEdit; Edit04: TEdit; Label01: TLabel; Label02: TLabel; Label03: TLabel; Label04: TLabel; Label05: TLabel; Label06: TLabel; Timer01: TTimer; Timer02: TTimer; procedure BitBtn01Click(Sender: TObject); procedure Timer01Timer(Sender: TObject); procedure FormCreate(Sender: TObject); procedure BitBtn02Click(Sender: TObject); procedure Timer02Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.dfm} procedure HSVToRGB(Const H, S, V: Real; { 'H' In '000' To '001', 'S' In '000' To '001', 'V' In '000' To '255' } Out R, G, B: Real); { 'R' In '000' To '255', 'G' In '000' To '255', 'B' In '000' To '255' } const SectionSize = 60/360; var F: real; P, Q, T: real; Section: real; SectionIndex: integer; begin if H < 0 then begin R:= V; G:= R; B:= R; end else begin Section:= H/SectionSize; SectionIndex:= Floor(Section); F:= Section - SectionIndex; P:= V * ( 1 - S ); Q:= V * ( 1 - S * F ); T:= V * ( 1 - S * ( 1 - F ) ); case SectionIndex of 0: begin R:= V; G:= T; B:= P; end; 1: begin R:= Q; G:= V; B:= P; end; 2: begin R:= P; G:= V; B:= T; end; 3: begin R:= P; G:= Q; B:= V; end; 4: begin R:= T; G:= P; B:= V; end; else begin R:= V; G:= P; B:= Q; end; end; end; end; procedure RGBToHSV(Const R, G, B: Real; { 'R' In '000' To '255', 'G' In '000' To '255', 'B' In '000' To '255' } Out H, S, V: Real); { 'H' In '000' To '001', 'S' In '000' To '001', 'V' In '000' To '255' } var Range: real; RGB: array[0..2] of real; MinIndex, MaxIndex: integer; begin RGB[0]:= R; RGB[1]:= G; RGB[2]:= B; MinIndex:= 0; if G < R then MinIndex:= 1; if B < RGB[MinIndex] then MinIndex:= 2; MaxIndex:= 0; if G > R then MaxIndex:= 1; if B > RGB[MaxIndex] then MaxIndex:= 2; Range:= RGB[MaxIndex] - RGB[MinIndex]; if Range = 0 then begin H:= 0; S:= 0; V:= R; end else begin case MaxIndex of 0: begin H:= (G-B)/Range; end; 1: begin H:= 2 + (B-R)/Range; end; 2: begin H:= 4 + (R-G)/Range; end; end; S:= Range/RGB[MaxIndex]; V:= RGB[MaxIndex]; H:= H * (1/6); if H < 0 then H:= 1 + H; end; end; procedure TMainForm.BitBtn01Click(Sender: TObject); begin Timer01.Enabled := true; end; procedure TMainForm.BitBtn02Click(Sender: TObject); begin Timer01.Enabled := false; Timer02.Enabled := false; end; procedure TMainForm.FormCreate(Sender: TObject); const HueStandardisationFactor = 360; SaturationStandardisationFactor = 100; BrightnessStandardisationFactor = 100/255; var H, S, V, R, G, B: Real; begin R := 98; G := 128; B := 33; Label01.Font.Color := RGB(Round(R), Round(G), Round(B)); Edit01.Text := FloatToStr(Round(R)) + ' ' + FloatToStr(Round(G)) + ' ' + FloatToStr(Round(B)); RGBToHSV(R, G, B, H, S, V); Edit02.Text := FloatToStr(Round(H*HueStandardisationFactor)) + ' ' + FloatToStr(Round(S*SaturationStandardisationFactor)) + ' ' + FloatToStr(Round(V*BrightnessStandardisationFactor)); Label02.Caption := 'Starting RGB Value : ' + '(' + FloatToStr(R) + ' ' + FloatToStr(G) + ' ' + FloatToStr(V) + ')'; Label03.Caption := 'Starting HSV Value : ' + '(' + FloatToStr(Round(H*HueStandardisationFactor)) + ' ' + FloatToStr(Round(S*SaturationStandardisationFactor)) + ' ' + FloatToStr(Round(V*BrightnessStandardisationFactor)) + ')'; end; procedure TMainForm.Timer01Timer(Sender: TObject); const HueStandardisationFactor = 360; SaturationStandardisationFactor = 100; BrightnessStandardisationFactor = 100/255; var Brightness : Integer; H1, S1, V1, R1, G1, B1: Real; H2, S2, V2, R2, G2, B2: Real; begin R1 := GetRValue(Label01.Font.Color); G1 := GetGValue(Label01.Font.Color); B1 := GetBValue(Label01.Font.Color); RGBToHSV(R1, G1, B1, H1, S1, V1); Brightness := Round(V1); Brightness := Brightness + 1; if Brightness >= 255 then begin Timer01.Enabled := false; Timer02.Enabled := true; end; H2 := H1; S2 := S1; V2 := Brightness; Edit03.Text := FloatToStr(Round(H2*HueStandardisationFactor)) + ' ' + FloatToStr(Round(S2*SaturationStandardisationFactor)) + ' ' + FloatToStr(Round(V2*BrightnessStandardisationFactor)); HSVToRGB(H2, S2, V2, R2, G2, B2); Label01.Font.Color := RGB(Round(R2), Round(G2), Round(B2)); Edit04.Font.Color := RGB(95, 25, 255); Edit04.Text := FloatToStr(Round(R2)) + ' ' + FloatToStr(Round(G2)) + ' ' + FloatToStr(Round(B2)); end; procedure TMainForm.Timer02Timer(Sender: TObject); const HueStandardisationFactor = 360; SaturationStandardisationFactor = 100; BrightnessStandardisationFactor = 100/255; var Brightness : Integer; H1, S1, V1, R1, G1, B1: Real; H2, S2, V2, R2, G2, B2: Real; begin R1 := GetRValue(Label01.Font.Color); G1 := GetGValue(Label01.Font.Color); B1 := GetBValue(Label01.Font.Color); RGBToHSV(R1, G1, B1, H1, S1, V1); Brightness := Round(V1); Brightness := Brightness - 1; if Brightness <= 25 then begin Timer01.Enabled := true; Timer02.Enabled := false; end; H2 := H1; S2 := S1; V2 := Brightness; Edit03.Text := FloatToStr(Round(H2*HueStandardisationFactor)) + ' ' + FloatToStr(Round(S2*SaturationStandardisationFactor)) + ' ' + FloatToStr(Round(V2*BrightnessStandardisationFactor)); HSVToRGB(H2, S2, V2, R2, G2, B2); Label01.Font.Color := RGB(Round(R2), Round(G2), Round(B2)); Edit04.Font.Color := RGB(15, 135, 255); Edit04.Text := FloatToStr(Round(R2)) + ' ' + FloatToStr(Round(G2)) + ' ' + FloatToStr(Round(B2)); end; end. Hue会发生变化(但不应该发生这种情况),尽管我已将所有必需的变量用作{ {1}}

    因此颜色偏离原始颜色。

    我无法找到它来应用更高的精度,以避免色移。

1 个答案:

答案 0 :(得分:3)

您应该将原始颜色存储在某个位置并使计算始终保持该值。中间值应仅用于显示,而不用于计算下一步。转换错误往往会随着时间的推移而增加。