Nadesłany przez Tomasz Lubiński, 05 listopada 2007 01:00
Kod przedstawiony poniżej przedstawia główną część rozwiązania problemu.Pobierz pełne rozwiązanie.
Jeżeli nie odpowiada Ci sposób formatowania kodu przez autora skorzystaj z pretty printer'a i dostosuj go automatycznie do siebie.
HSV - Delphi/Unit1.pas:
// Model HSV // www.algorytm.org // (c)2007 by Tomasz Lubinski unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Math; type TForm1 = class(TForm) GroupBox1: TGroupBox; Model: TImage; Label1: TLabel; Label2: TLabel; Label3: TLabel; Button1: TButton; WidthVal: TEdit; HeightVal: TEdit; ShiftVal: TEdit; Button2: TButton; GroupBox2: TGroupBox; ProbeLarge: TImage; ProbeSmall: TImage; Probe: TImage; Label4: TLabel; Label5: TLabel; Label6: TLabel; HVal: TEdit; SVal: TEdit; VVal: TEdit; HButton: TRadioButton; SButton: TRadioButton; VButton: TRadioButton; GroupBox3: TGroupBox; AllLayers: TImage; LayerH: TImage; LayerS: TImage; LayerV: TImage; Label7: TLabel; Label8: TLabel; Label9: TLabel; Label10: TLabel; procedure Button1Click(Sender: TObject); procedure DrawArc(x: Real; y: Real; r1: Real; s: Real; v: Real; shift: Integer); procedure FillCircle(x: Real; y: Real; maxr: Integer; shift: Integer); procedure Button2Click(Sender: TObject); procedure ReDrawProbe(Sender: TObject); procedure ReDrawRectangle(Sender: TObject); procedure HButtonClick(Sender: TObject); procedure SButtonClick(Sender: TObject); procedure VButtonClick(Sender: TObject); procedure HValChange(Sender: TObject); procedure SValChange(Sender: TObject); procedure VValChange(Sender: TObject); procedure ProbeLargeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ProbeSmallMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormActivate(Sender: TObject); procedure DrawLayers(); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} function fmod(x: double; y: double): double; begin Result := x - Int(x / y) * y; end; procedure hsv2rgb(hue: double; sat: double; val: double; var red: double; var grn: double; var blu: double); var i, f, p, q, t: double; begin red := 0; grn := 0; blu := 0; if val=0 then begin red := 0; grn := 0; blu := 0; end else begin hue := hue/60; i := floor(hue); f := hue-i; p := val*(1-sat); q := val*(1-(sat*f)); t := val*(1-(sat*(1-f))); if i=0 then begin red:=val; grn:=t; blu:=p; end else if i=1 then begin red:=q; grn:=val; blu:=p; end else if i=2 then begin red:=p; grn:=val; blu:=t; end else if i=3 then begin red:=p; grn:=q; blu:=val; end else if i=4 then begin red:=t; grn:=p; blu:=val; end else if i=5 then begin red:=val; grn:=p; blu:=q; end; end; end; procedure rgb2hsv(var hue: double; var sat: double; var val: double; red: double;grn: double; blu:double); var x, f, i: double; begin x := MIN(MIN(red, grn), blu); val := MAX(MAX(red, grn), blu); if x = val then begin hue := 0; sat := 0; end else begin if red = x then f := grn-blu else if grn = x then f := blu-red else f := red-grn; if red = x then i := 3 else if grn = x then i := 5 else i := 1; hue := fmod((i-f/(val-x))*60, 360); sat := ((val-x)/val); end; end; procedure TForm1.DrawArc(x: Real; y: Real; r1: Real; s: Real; v: Real; shift: Integer); var h, r, g, b, r2, incr, i: double; begin incr := 45 / r1; r2 := r1 / 3.0; i := 180; while (i<360) do begin h := fmod(i + shift, 360); HSV2RGB(h, s, v, r, g, b); Model.Canvas.Pixels[Round(r1*cos(i*Pi/180)+x), Round(-r2*sin(i*Pi/180)+y)] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); i := i+incr; end; end; procedure TForm1.FillCircle(x: Real; y: Real; maxr: Integer; shift: Integer); var h, s, v, r, g, b, r1, r2, incr, i: double; j: integer; begin for j:=1 to maxr do begin r1 := j; r2 := r1 / 3.0; s := j / (maxr); v := 1; incr := 45 / r1; i := 0; while (i<360) do begin h := fmod(i + shift, 360); HSV2RGB(h, s, v, r, g, b); Model.Canvas.Pixels[Round(r1*cos(i*Pi/180)+x), Round(-r2*sin(i*Pi/180)+y)] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); i := i+incr; end; end; end; procedure TForm1.Button1Click(Sender: TObject); var s,v,step,r1,r2,incr,i: Real; width, height, shift, shift_x, shift_y, k: Integer; begin Model.Canvas.Brush.Color := clWhite; Model.Canvas.Rectangle(0, 0, Model.Width, Model.Height); width := StrToInt(WidthVal.Text); height := StrToInt(HeightVal.Text); shift := StrToInt(ShiftVal.Text); shift_x := Model.Width div 2; shift_y := 50; step := (width*1.0)/height; for k:=height-1 downto 0 do begin s := 1.0 - (1 / (width - (step*k))); v := 1 - (k / height); DrawArc(shift_x, shift_y + k, width - (step*k), s, v, shift); end; FillCircle(shift_x, shift_y, width, shift); //draw H, S and V crosses r1 := width; r2 := r1 / 3.0; shift_y := shift_y - 10; incr := 45 / r1; i := 0; while (i<270) do begin Model.Canvas.Pixels[Round(r1*cos(i*Pi/180)+shift_x), Round(-r2*sin(i*Pi/180)+shift_y)] := 0; i := i + incr; end; Model.Canvas.MoveTo(Round(r1*cos(270*Pi/180)+shift_x), Round(-r2*sin(270*Pi/180)+shift_y)); Model.Canvas.LineTo(Round(r1*cos(270*Pi/180)+shift_x-5), Round(-r2*sin(270*Pi/180)+shift_y-5)); Model.Canvas.MoveTo(Round(r1*cos(270*Pi/180)+shift_x), Round(-r2*sin(270*Pi/180)+shift_y)); Model.Canvas.LineTo(Round(r1*cos(270*Pi/180)+shift_x-5), Round(-r2*sin(270*Pi/180)+shift_y+5)); Model.Canvas.TextOut(Round(r1*cos(140*Pi/180)+shift_x-30), Round(-r2*sin(140*Pi/180)+shift_y+5), 'H'); Model.Canvas.MoveTo(Round(shift_x - r1 - 10), Round(shift_y + r2/2 + height)); Model.Canvas.LineTo(Round(shift_x - r1 - 10), Round(shift_y + r2/2)); Model.Canvas.LineTo(Round(shift_x - r1 - 15), Round(shift_y + r2/2 + 5)); Model.Canvas.MoveTo(Round(shift_x - r1 - 10), Round(shift_y + r2/2)); Model.Canvas.LineTo(Round(shift_x - r1 - 5), Round(shift_y + r2/2 + 5)); Model.Canvas.TextOut(Round(shift_x - r1 - 20), Round(shift_y + r2/2 + 15), 'V'); Model.Canvas.MoveTo(Round(shift_x), Round(shift_y + r2/2 + height)); Model.Canvas.LineTo(Round(shift_x - r1), Round(shift_y + r2/2 + height)); Model.Canvas.LineTo(Round(shift_x - r1 + 5), Round(shift_y + r2/2 + height - 5)); Model.Canvas.MoveTo(Round(shift_x - r1), Round(shift_y + r2/2 + height)); Model.Canvas.LineTo(Round(shift_x - r1 + 5), Round(shift_y + r2/2 + height + 5)); Model.Canvas.TextOut(Round(shift_x - r1 + 15), Round(shift_y + r2/2 + height - 15), 'S'); Model.Refresh(); end; procedure TForm1.Button2Click(Sender: TObject); var i: Integer; begin for i:=0 to 36 do begin ShiftVal.Text := IntToStr(i * 10); Button1Click(Sender); end; end; procedure TForm1.ReDrawProbe(Sender: TObject); var h, s, v, r, g, b: double; i, j: Integer; begin h := StrToInt(HVal.Text); s := StrToInt(SVal.Text) / 100.0; v := StrToInt(VVal.Text) / 100.0; ProbeSmall.Canvas.Brush.Color := clWhite; ProbeSmall.Canvas.Rectangle(0, 0, ProbeSmall.Width, ProbeSmall.Height); if (HButton.Checked) then begin s := 1; v := 1; for i:=0 to 255 do begin h := (i * 359.0) / 255; HSV2RGB(h, s, v, r, g, b); ProbeSmall.Canvas.Pixels[1, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[2, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[3, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[4, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[5, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[6, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[7, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[8, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[9, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[10, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[11, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[12, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[13, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[14, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[15, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end end else if (SButton.Checked) then begin for i:=0 to 255 do begin s := i / 255.0; HSV2RGB(h, s, v, r, g, b); ProbeSmall.Canvas.Pixels[1, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[2, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[3, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[4, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[5, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[6, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[7, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[8, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[9, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[10, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[11, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[12, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[13, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[14, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[15, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end end else if (VButton.Checked) then begin for i:=0 to 255 do begin v := i / 255.0; HSV2RGB(h, s, v, r, g, b); ProbeSmall.Canvas.Pixels[1, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[2, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[3, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[4, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[5, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[6, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[7, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[8, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[9, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[10, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[11, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[12, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[13, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[14, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); ProbeSmall.Canvas.Pixels[15, i] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end end; h := StrToInt(HVal.Text); s := StrToInt(SVal.Text) / 100.0; v := StrToInt(VVal.Text) / 100.0; ProbeLarge.Canvas.Brush.Color := clWhite; ProbeLarge.Canvas.Rectangle(0, 0, ProbeLarge.Width, ProbeLarge.Height); if (HButton.Checked) then begin for i:=0 to 255 do begin for j:=0 to 255 do begin s := i / 255.0; v := j / 255.0; HSV2RGB(h, s, v, r, g, b); ProbeLarge.Canvas.Pixels[i, 255-j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end; end; end else if (SButton.Checked) then begin for i:=0 to 255 do begin for j:=0 to 255 do begin h := (i * 359.0) / 255; v := j / 255.0; HSV2RGB(h, s, v, r, g, b); ProbeLarge.Canvas.Pixels[i, 255-j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end; end; end else if (VButton.Checked) then begin for i:=0 to 255 do begin for j:=0 to 255 do begin h := (i * 359.0) / 255; s := j / 255.0; HSV2RGB(h, s, v, r, g, b); ProbeLarge.Canvas.Pixels[i, 255-j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end; end; end; ReDrawRectangle(Sender); end; procedure TForm1.ReDrawRectangle(Sender: TObject); var h, s, v, r, g, b: double; begin h := StrToInt(HVal.Text); s := StrToInt(SVal.Text) / 100.0; v := StrToInt(VVal.Text) / 100.0; HSV2RGB(h, s, v, r, g, b); Probe.Canvas.Brush.Color := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); Probe.Canvas.Rectangle(0, 0, Probe.Width, Probe.Height); if (HButton.Checked) then begin ProbeSmall.Canvas.Ellipse(5, Round(h*255/359-3), 13, Round(h*255/359+3)); ProbeLarge.Canvas.Ellipse(Round(s*255-3), Round(255-v*255-3), Round(s*255+3), Round(255-v*255+3)); end else if (SButton.Checked) then begin ProbeSmall.Canvas.Ellipse(5, Round(s*255-3), 13, Round(s*255+3)); ProbeLarge.Canvas.Ellipse(Round(h*255/359-3), Round(255-v*255-3), Round(h*255/359+3), Round(255-v*255+3)); end else if (VButton.Checked) then begin ProbeSmall.Canvas.Ellipse(5, Round(v*255-3), 13, Round(v*255+3)); ProbeLarge.Canvas.Ellipse(Round(h*255/359-3), Round(255-s*255-3), Round(h*255/359+3), Round(255-s*255+3)); end; end; procedure TForm1.HButtonClick(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.SButtonClick(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.VButtonClick(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.HValChange(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.SValChange(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.VValChange(Sender: TObject); begin ReDrawProbe(Sender); end; procedure TForm1.ProbeLargeMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (HButton.Checked) then begin SVal.Text := IntToStr((X*100) div 255); VVal.Text := IntToStr(100-(Y*100) div 255); end else if (SButton.Checked) then begin HVal.Text := IntToStr((X*359) div 255); VVal.Text := IntToStr(100-(Y*100) div 255); end else if (VButton.Checked) then begin HVal.Text := IntToStr((X*359) div 255); SVal.Text := IntToStr(100-(Y*100) div 255); end; end; procedure TForm1.ProbeSmallMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if (HButton.Checked) then begin HVal.Text := IntToStr((Y*359) div 255); end else if (SButton.Checked) then begin SVal.Text := IntToStr((Y*100) div 255); end else if (VButton.Checked) then begin VVal.Text := IntToStr((Y*100) div 255); end; end; procedure TForm1.DrawLayers(); var r, g, b, h, s, v: double; color: TColor; i, j: Integer; begin for i:=0 to AllLayers.Width-1 do for j:=0 to AllLayers.Height-1 do begin color := AllLayers.Canvas.Pixels[i, j]; r := (color and $FF) / 255.0; g := ((color and $FF00) shr 8) / 255.0; b := ((color and $FF0000) shr 16) / 255.0; RGB2HSV(h, s, v, r, g, b); HSV2RGB(h, 1, 1, r, g, b); LayerH.Canvas.Pixels[i, j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); HSV2RGB(0, s, 1, r, g, b); LayerS.Canvas.Pixels[i, j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); HSV2RGB(0, 0, v, r, g, b); LayerV.Canvas.Pixels[i, j] := Round((r*255) + (Round(g*255) shl 8) + (Round(b*255) shl 16)); end; end; procedure TForm1.FormActivate(Sender: TObject); begin ReDrawProbe(Sender); Button1Click(Sender); DrawLayers(); end; end.