algorytm.org

Implementacja w Delphi/Pascal

Baza Wiedzy
wersja offline serwisu przeznaczona na urządzenia z systemem Android
Darowizny
darowiznaWspomóż rozwój serwisu
Nagłówki RSS
Artykuły
Implementacje
Komentarze
Forum
Bookmarki






Sonda
Implementacji w jakim języku programowania poszukujesz?

Model HSV - Implementacja w Delphi/Pascal
Ocena użytkownikóww: *****  / 3
SłabyŚwietny
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.
Dodaj komentarz