unit UPSPFrame;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Spin, ExtCtrls, Couleur;
const
  LibEpsilon: Real=1E-8;
  LibRadian: Real=3.1415926536/180;
  RectPSP: TRect = (Left:44;Top:44;right:150;bottom:150);
  RectActCol : TRect = (Left:21;Top:20;Right:69;Bottom:70);
  RectPreCol : TRect = (Left:21;Top:95;Right:69;Bottom:145);
  CerclePSPCoord : TRect = (Left:0;Top:0;right:195;bottom:195);

  MaxPixelCount   =  32768;

type
  TClicZonePSP = (CZPSPnone,CZPSPCercle,CZPSPCarre);
  TLigne = array of byte;
  TLigneAlia = Array of integer;

  pRGBArray  =  ^TRGBArray;
  TRGBArray  =  ARRAY[0..MaxPixelCount-1] OF TRGBTriple;

  TFramePSP = class(TFrame)
    CerclePSP: TImage;
    GroupBox1: TGroupBox;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    SPRPSP: TSpinEdit;
    SPVPSP: TSpinEdit;
    SPBPSP: TSpinEdit;
    SPTPSP: TSpinEdit;
    SPSPSP: TSpinEdit;
    SPLPSP: TSpinEdit;
    ImgCoulPSP: TImage;
    Label1: TLabel;
    Label2: TLabel;
    EHexaPSP: TEdit;
    EHTMLPSP: TEdit;
    procedure SPTSLPSPChange(Sender: TObject);
    procedure SPTSLPSPKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure SPTSLPSPKeyPress(Sender: TObject; var Key: Char);
    procedure SPRVBPSPChange(Sender: TObject);
    procedure CerclePSPMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure CerclePSPMouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure CerclePSPMouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ImgCoulPSPMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure EHTMLPSPChange(Sender: TObject);
    procedure EHexaPSPChange(Sender: TObject);
  private
    { D閏larations priv閑s }
    PasCercle,PasCarre : Integer;
    ClickImg : TClicZonePSP;
    function LibAngle3Points(X1, Y1, Xc, Yc, X2, Y2: Real): Real;
    function LibAnglePoints(X1, Y1, X2, Y2: Real): Real;
    procedure LibAngle360(var Angle: Real);
    function LibDistancePoints(X1, Y1, X2, Y2: Real): Real;
    function LibArcCosRadians(CosAngle: Real): Real;
    function LibArcSinRadians(SinAngle: Real): Real;
    procedure LibRotationPoint(Xc, Yc: Real; Angle: Real; X1, Y1: Real; var X2, Y2: Real);
    procedure LibPointSurEllipse(Xc, Yc: Real; RayonX, RayonY: Real; Angle: Real; var X, Y: Real);
    function LibArcTan(TanAngle: Real): Real;

    procedure DrawPSP();
    procedure DrawCoul();
    procedure AffectModif();
  public
    { D閏larations publiques }
    Couleur : TCouleur;
    OldColor : TColor;
    procedure DrawMark();
    procedure MAJCoul;
    procedure InitPSP;
    procedure CreateFrame;
    procedure FreeFrame;
  end;

implementation



{$R *.dfm}

{ TFramePSP }

procedure TFramePSP.CreateFrame;
var
  Temp : TRVB;
  R :TRect;
begin
  ClickImg := CZPSPnone;
  Couleur := TCouleur.Create;
  Temp.R := 0;
  Temp.V := 0;
  Temp.B := 0;
  Couleur.RVB := Temp;
  Brush.Style := bsClear;
  PasCercle := (CerclePSP.Width-CerclePSPCoord.Right)div 2;
  PasCarre := PasCercle;

  ImgCoulPSP.Picture.Bitmap.Height := ImgCoulPSP.Height;
  ImgCoulPSP.Picture.Bitmap.Width := ImgCoulPSP.Width;
  ImgCoulPSP.Picture.Bitmap.PixelFormat := pf24bit;
  ImgCoulPSP.Canvas.Brush.Color := ColorToRGB(clBtnFace);
  ImgCoulPSP.Canvas.Pen.Color := ColorToRGB(clBtnFace);

  Rectangle(ImgCoulPSP.Canvas.Handle,0,0,ImgCoulPSP.Width,ImgCoulPSP.Height);
  ImgCoulPSP.Canvas.Pen.Color := clBlack;
  R := Rect(0,5,ImgCoulPSP.Width,25);
  DrawText(ImgCoulPSP.Canvas.Handle,'泅犁祸',6,R,DT_CENTER);
  R := Rect(0,80,ImgCoulPSP.Width,100);
  DrawText(ImgCoulPSP.Canvas.Handle,'捞傈祸',6,R,DT_CENTER);
  ImgCoulPSP.Canvas.Brush.Color := Couleur.Color;
  Rectangle(ImgCoulPSP.Canvas.Handle,RectActCol.Left,RectActCol.Top,RectActCol.Right,RectActCol.Bottom);
  ImgCoulPSP.Canvas.Brush.Color := OldColor;
  Rectangle(ImgCoulPSP.Canvas.Handle,RectPreCol.Left,RectPreCol.Top,RectPreCol.Right,RectPreCol.Bottom);

  CerclePSP.Picture.Bitmap.PixelFormat := pf32bit;
  CerclePSP.Picture.Bitmap.width := CerclePSP.width;
  CerclePSP.Picture.Bitmap.height := CerclePSP.Height;
end;
procedure TFramePSP.DrawCoul;
begin
  ImgCoulPSP.Canvas.Brush.Color := Couleur.Color;
  Rectangle(ImgCoulPSP.Canvas.Handle,RectActCol.Left,RectActCol.Top,RectActCol.Right,RectActCol.Bottom);
  ImgCoulPSP.Canvas.Brush.Color := OldColor;
  Rectangle(ImgCoulPSP.Canvas.Handle,RectPreCol.Left,RectPreCol.Top,RectPreCol.Right,RectPreCol.Bottom);
  ImgCoulPSP.Repaint;
end;

procedure TFramePSP.DrawMark;
  procedure DrawCircle(X,Y,R:Integer);
  begin
    Ellipse(CerclePSP.Canvas.Handle,X-R,Y-R,X+R,Y+R);
  end;
var
  Angle : Integer;
  X,Y : Real;
  C_X,C_Y : Integer;
begin
      X := round((Couleur.TSL.S*(RectPSP.Right-RectPSP.Left)) + (PasCarre+RectPSP.Left));
      Y := round((Couleur.TSL.L*(RectPSP.Bottom-RectPSP.Top)) + RectPSP.Top);
      DrawCircle(Round(X),Round(Y),5);
      C_X := PasCarre+RectPSP.Left+(RectPSP.Right-RectPSP.Left)div 2;
      C_Y := RectPSP.Top+(RectPSP.Bottom-RectPSP.Top)div 2;
      Angle := Round(Couleur.TSL.T*360);
      LibRotationPoint(C_X, C_Y, -Angle, C_X, C_Y-((CerclePSPCoord.Bottom-20) div 2), X,Y);
      DrawCircle(Round(X),Round(Y),5);
end;

procedure TFramePSP.DrawPSP;
  procedure DrawRect;
  var
    PLigneCercle : pointer;
    I, J : Integer;
    Coul : TCouleur;
    Coul2 : TTSL;
  begin
    Coul := TCouleur.Create;
    Coul.Assign(Couleur);
    Coul2 := Coul.TSL;
    for J :=RectPSP.Top to RectPSP.Bottom do
    begin
      PLigneCercle := CerclePSP.Picture.Bitmap.ScanLine[J];
      Coul2.L := (J-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top);
      for I := RectPSP.Left to (RectPSP.Right) do
        begin
          Coul2.S := (I-RectPSP.Left)/(RectPSP.Right-RectPSP.Left);
          Coul.TSL := Coul2;
          TLigne(PLigneCercle)[(I+PasCarre)*4    ] := Coul.RVB.B;
          TLigne(PLigneCercle)[(I+PasCarre)*4 + 1] := Coul.RVB.V;
          TLigne(PLigneCercle)[(I+PasCarre)*4 + 2] := Coul.RVB.R;
        end;
    end;
    Coul.free;
  end;
begin
  DrawRect;
  DrawMark;
  DrawCoul;
  CerclePSP.Picture.Bitmap.Modified := true;
end;

procedure TFramePSP.FreeFrame;
begin
  Couleur.Free;
end;

procedure TFramePSP.InitPSP;
var
  GCercle,PCercle,Disque : HRGN;
  PLigneCercle : pointer;
  I, J : Integer;
  C_X, C_Y : Integer;
//  Bufz : Integer;
  Coul : TCouleur;
  Coul2 : TTSL;
  Val : TTSL;
  TabCol : array[0..359]of TRVB;
  Angle : Integer;
begin

  Coul := TCouleur.Create;

  GCercle := CreateEllipticRgn(CerclePSPCoord.Left,CerclePSPCoord.Top,CerclePSPCoord.Right,CerclePSPCoord.Bottom);
  PCercle := CreateEllipticRgn((CerclePSPCoord.Left+20),(CerclePSPCoord.Top+20),(CerclePSPCoord.Right-20),(CerclePSPCoord.Bottom-20));
  Disque := CreateRectRgn(0,0,2,2);
  CombineRgn(Disque,GCercle,PCercle,RGN_DIFF);

  Val.S := 1;
  Val.L := 0.47;
  for I := 0 to 359 do
  begin
    Val.T := I/359;
    Coul.TSL := Val;
    TabCol[I] := Coul.RVB;
  end;

  C_X :=CerclePSPCoord.Left+98;
  C_Y :=CerclePSPCoord.Left+98;
  Val.S := 0.93;
  Val.L := 0.47;
{  for J := 0 to CerclePSPCoord.Bottom*3 do
  begin
    PLigneCercle := big_bmp.ScanLine[J];
    for I := 0 to CerclePSPCoord.Bottom*3 do
      if PtInRegion(Disque,I,J) then
      begin
        Angle := Round(LibAngle3Points(C_X,0,C_X,C_Y,I,J));
        if Angle = 360 then
          Angle := 0;
        Angle := 359-Angle;
        TLigne(PLigneCercle)[I*3    ] := TabCol[Angle].B;
        TLigne(PLigneCercle)[I*3 + 1] := TabCol[Angle].V;
        TLigne(PLigneCercle)[I*3 + 2] := TabCol[Angle].R;

      end
      else
      begin
        Coul.Color := ColorToRGB(clBtnFace);
        TLigne(PLigneCercle)[I*3] := Coul.RVB.B;
        TLigne(PLigneCercle)[I*3 + 1] := Coul.RVB.V;
        TLigne(PLigneCercle)[I*3 + 2] := Coul.RVB.R;

      end;
  end;
}

  CerclePSP.Canvas.Pen.Color := ColorToRGB(clBtnFace);
  CerclePSP.Canvas.Brush.Color := ColorToRGB(clBtnFace);
  Rectangle(CerclePSP.Canvas.Handle,0,0,CerclePSP.Width,CerclePSP.Height);

  for J := 0 to CerclePSPCoord.Bottom do
  begin
    PLigneCercle := CerclePSP.Picture.Bitmap.ScanLine[CerclePSPCoord.Top+J];
    for I := 0 to CerclePSPCoord.Bottom do
      if PtInRegion(Disque,CerclePSPCoord.Left+I,CerclePSPCoord.Top+J) then
      begin
        Angle := Round(LibAngle3Points(C_X,0,C_X,C_Y,I,J));
        if Angle = 360 then
          Angle := 0;
        Angle := 359-Angle;
        TLigne(PLigneCercle)[(PasCercle+I)*4 + 0] := TabCol[Angle].B;
        TLigne(PLigneCercle)[(PasCercle+I)*4 + 1] := TabCol[Angle].V;
        TLigne(PLigneCercle)[(PasCercle+I)*4 + 2] := TabCol[Angle].R;

      end;
  end;
//  CerclePSP.Picture.Bitmap.Modified := true;
//  AntiAliasingWithColor(CerclePSP.Picture.Bitmap, ColorToRGB(clBtnFace));//15526360
  Coul.Assign(Couleur);
  Coul2 := Coul.TSL;

  for J :=RectPSP.Top to RectPSP.Bottom do
  begin
    PLigneCercle := CerclePSP.Picture.Bitmap.ScanLine[J];
    Coul2.L := (J-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top);
    for I := RectPSP.Left to (RectPSP.Right) do
      begin
        Coul2.S := (I-RectPSP.Left)/(RectPSP.Right-RectPSP.Left);
        Coul.TSL := Coul2;
        TLigne(PLigneCercle)[(I+PasCarre)*4    ] := Coul.RVB.B;
        TLigne(PLigneCercle)[(I+PasCarre)*4 + 1] := Coul.RVB.V;
        TLigne(PLigneCercle)[(I+PasCarre)*4 + 2] := Coul.RVB.R;
      end;
  end;
  CerclePSP.Canvas.Pen.Color := $FFFFFF;
  CerclePSP.Canvas.Pen.Mode := pmXor;
  CerclePSP.Canvas.Brush.Style := bsClear;
  DrawMark;
  CerclePSP.Picture.Bitmap.modified := true;

  Coul.Free;

end;

procedure TFramePSP.LibAngle360(var Angle: Real);
begin
  while (Angle<0) do
    Angle:=Angle+360;
  while (Angle>=360) do
    Angle:=Angle-360;
end;

function TFramePSP.LibAngle3Points(X1, Y1, Xc, Yc, X2, Y2: Real): Real;
var
  Angle1, Angle2, Angle: Real;
begin
  Angle1:=LibAnglePoints(Xc, Yc, X1, Y1);
  Angle2:=LibAnglePoints(Xc, Yc, X2, Y2);
  Angle:=Angle2-Angle1;
  LibAngle360(Angle);
  LibAngle3Points:=Angle;
end;

procedure TFramePSP.LibRotationPoint(Xc, Yc, Angle, X1, Y1: Real; var X2,Y2: Real);
var
  Angle0: Real;
  Distance: Real;
begin
  Angle0:=LibAnglePoints(Xc, Yc, X1, Y1);
  Distance:=LibDistancePoints(Xc, Yc, X1, Y1);
  LibPointSurEllipse(Xc, Yc, Distance, Distance, Angle0+Angle, X2, Y2);
end;

procedure TFramePSP.LibPointSurEllipse(Xc, Yc, RayonX, RayonY, Angle: Real;
  var X, Y: Real);
var
  Angle1, AngleA: Real;
  A, B: Real;
begin
  LibAngle360(Angle);
  Angle1:=90-Angle;
  A:=Cos(Angle1*LibRadian)*RayonX;
  B:=Sin(Angle1*LibRadian)*RayonY;
  if (Abs(B)<LibEpsilon) then
    if (Abs(Angle-90)<1E-7) then
      AngleA:=90
    else
      AngleA:=270
  else
  begin
    AngleA:=LibArcTan(A/B);
    if (Angle<90) then
    else
      if (Angle<270) then
        AngleA:=AngleA+180
      else
        AngleA:=AngleA+0;
  end;
  Y:=Yc+Sin(AngleA*LibRadian)*RayonY;
  X:=Xc+Cos(AngleA*LibRadian)*RayonX;
end;

function TFramePSP.LibArcTan(TanAngle: Real): Real;
begin
  LibArcTan:=Arctan(TanAngle)/LibRadian;
end;

function TFramePSP.LibAnglePoints(X1, Y1, X2, Y2: Real): Real;
var
  Distance, CosAngle, Angle: Real;
begin
  Distance:=LibDistancePoints(X1, Y1, X2, Y2);
  if (Abs(Distance)<LibEpsilon) then
    Angle:=0
  else
  begin
    CosAngle:=Abs(X1-X2)/Distance;
    Angle:=LibArcCosRadians(CosAngle);
    if (Abs(Y1-Y2)>=LibEpsilon) and (Y2<Y1) then Angle:=-Angle;
    if (Abs(X1-X2)>=LibEpsilon) and (X2<X1) then Angle:=Pi-Angle;
    if (Abs(Angle)<LibEpsilon) then Angle:=0;
    if (Angle<0) then Angle:=Angle+2*Pi;
    Angle:=Angle/LibRadian;
  end;
  LibAnglePoints:=Angle;
end;

function TFramePSP.LibArcCosRadians(CosAngle: Real): Real;
var
  Angle: Real;
begin
  Angle:=Pi/2-LibArcSinRadians(CosAngle);
  LibArcCosRadians:=Angle;

end;

function TFramePSP.LibArcSinRadians(SinAngle: Real): Real;
var
  Diviseur, Angle: Real;
begin
  Diviseur:=Sqrt(1-Sqr(SinAngle));
  if (Abs(Diviseur)<LibEpsilon) then
    if (SinAngle>0) then
      Angle:=Pi/2
    else
      Angle:=-Pi/2
  else
    Angle:=ArcTan(SinAngle/Diviseur);
  LibArcSinRadians:=Angle;
end;

function TFramePSP.LibDistancePoints(X1, Y1, X2, Y2: Real): Real;
begin
  LibDistancePoints:=Sqrt(Sqr(Y2-Y1)+Sqr(X2-X1));
end;

procedure TFramePSP.SPTSLPSPChange(Sender: TObject);
var
  TSLPSP : TTSLPSP;
begin
 if TSpinEdit(Sender).Text<>'' then
 begin
   DrawMark;
   if TSpinEdit(Sender).Value > 255 then
     TSpinEdit(Sender).Value := 255;
   TSLPSP.T := SPTPSP.Value;
   TSLPSP.S := SPSPSP.Value;
   TSLPSP.L := SPLPSP.Value;
   Couleur.TSLPSP := TSLPSP;

   SPRPSP.OnChange := nil;
   SPVPSP.OnChange := nil;
   SPBPSP.OnChange := nil;
   SPRPSP.Value := Couleur.RVB.R;
   SPVPSP.Value := Couleur.RVB.V;
   SPBPSP.Value := Couleur.RVB.B;
   SPRPSP.Modified := true;
   SPVPSP.Modified := true;
   SPBPSP.Modified := true;
   SPRPSP.OnChange := SPRVBPSPChange;
   SPVPSP.OnChange := SPRVBPSPChange;
   SPBPSP.OnChange := SPRVBPSPChange;
   EHexaPSP.Text := '$'+IntToHex(Couleur.Color,6);
   EHTMLPSP.Text := '#'+Couleur.HTML;
   DrawPSP;
 end;
end;

procedure TFramePSP.SPTSLPSPKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key = VK_SUBTRACT then
    Key := 0;
end;

procedure TFramePSP.SPTSLPSPKeyPress(Sender: TObject; var Key: Char);
begin
  if (Key='-')or(Key='+') then
    Key := #0;
end;

procedure TFramePSP.SPRVBPSPChange(Sender: TObject);
var
  RVB : TRVB;
begin
 if TSpinEdit(Sender).Text<>'' then
 begin
   DrawMark;

   if TSpinEdit(Sender).Value > 255 then
     TSpinEdit(Sender).Value := 255;
   RVB.R := SPRPSP.Value;
   RVB.V:= SPVPSP.Value;
   RVB.B:= SPBPSP.Value;
   Couleur.RVB := RVB;
   SPTPSP.OnChange := nil;
   SPSPSP.OnChange := nil;
   SPLPSP.OnChange := nil;
   SPTPSP.Value := Couleur.TSLPSP.T;
   SPSPSP.Value := Couleur.TSLPSP.S;
   SPLPSP.Value := Couleur.TSLPSP.L;
   SPTPSP.Modified := true;
   SPSPSP.Modified := true;
   SPLPSP.Modified := true;
   SPTPSP.OnChange := SPTSLPSPChange;
   SPSPSP.OnChange := SPTSLPSPChange;
   SPLPSP.OnChange := SPTSLPSPChange;

   EHexaPSP.OnChange:=nil;
   EHexaPSP.Text := '$'+IntToHex(Couleur.Color,6);
   EHexaPSP.OnChange:=EHexaPSPChange;

   EHTMLPSP.OnChange:=nil;
   EHTMLPSP.Text := '#'+Couleur.HTML;
   EHTMLPSP.OnChange:=EHTMLPSPChange;

   DrawPSP;
 end;
end;

procedure TFramePSP.CerclePSPMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var  
  GCercle,PCercle,Disque, Carre : HRGN;
  TSLPSP : TTSLPSP;
  C_X,C_Y : Integer;
  Angle : Integer;
begin
  GCercle := CreateEllipticRgn(PasCercle+CerclePSPCoord.Left,CerclePSPCoord.Top,PasCercle+CerclePSPCoord.Right,CerclePSPCoord.Bottom);
  PCercle := CreateEllipticRgn(PasCercle+CerclePSPCoord.Left+20,CerclePSPCoord.Top+20,PasCercle+CerclePSPCoord.Right-21,CerclePSPCoord.Bottom-21);
//  GCercle := CreateEllipticRgn(0,0,big_bmp.width-1,big_bmp.Height-1);
//  PCercle := CreateEllipticRgn(20*3,20*3,big_bmp.width-(20*3+1),big_bmp.Height-(20*3+1));
  Disque := CreateRectRgn(0,0,2,2);
  CombineRgn(Disque,GCercle,PCercle,RGN_DIFF);

  Carre := CreateRectRgn(PasCarre+RectPSP.Left,RectPSP.Top,PasCarre+RectPSP.Right,RectPSP.Bottom);
  if PtInRegion(Carre,X,Y) then
    ClickImg := CZPSPCarre
  else if PtInRegion(Disque,X,Y) then
    ClickImg := CZPSPCercle
  else
    ClickImg := CZPSPnone;
  if mbLeft=Button then
  case ClickImg of
    CZPSPCercle : begin
      C_X := PasCarre+RectPSP.Left+(RectPSP.Right-RectPSP.Left)div 2;
      C_Y := RectPSP.Top+(RectPSP.Bottom-RectPSP.Top)div 2;;
      Angle := Round(LibAngle3Points(C_X,0,C_X,C_Y,X,Y));
      if Angle = 360 then
        Angle := 0;
      Angle := 359-Angle;
      TSLPSP := Couleur.TSLPSP;
      TSLPSP.T := Round(255*(Angle/359));
      if TSLPSP.T <> Couleur.TSLPSP.T then
      begin
        DrawMark;
        Couleur.TSLPSP := TSLPSP;
        AffectModif;
        DrawPSP;
      end;
    end;
    CZPSPCarre : begin
      C_X := X;
      C_Y := Y;
      if C_X<PasCarre+RectPSP.Left then
        C_X:= PasCarre+RectPSP.Left
      else
      if C_X>PasCarre+RectPSP.Right then
        C_X:= PasCarre+RectPSP.Right;

      if C_Y<RectPSP.Top then
        C_Y:= RectPSP.Top
      else
      if C_Y>RectPSP.Bottom then
        C_Y:= RectPSP.Bottom;

      TSLPSP := Couleur.TSLPSP;
      TSLPSP.S := Round(255*((C_X-(PasCarre+RectPSP.Left))/(RectPSP.Right-RectPSP.Left)));
      TSLPSP.L := Round(255*((C_Y-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top)));
      DrawMark;
      Couleur.TSLPSP := TSLPSP;
      AffectModif;
      DrawCoul;
      DrawMark;
      CerclePSP.Repaint;
    end;
  end;
   
end;

procedure TFramePSP.CerclePSPMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
var
  TSLPSP : TTSLPSP;
  C_X,C_Y : Integer;
  Angle : Integer;
begin
  if ssLeft in Shift then
  case ClickImg of
    CZPSPCercle : begin
      C_X := PasCarre+RectPSP.Left+(RectPSP.Right-RectPSP.Left)div 2;
      C_Y := RectPSP.Top+(RectPSP.Bottom-RectPSP.Top)div 2;;
      Angle := Round(LibAngle3Points(C_X,0,C_X,C_Y,X,Y));
      if Angle = 360 then
        Angle := 0;
      Angle := 359-Angle;
      TSLPSP := Couleur.TSLPSP;
      TSLPSP.T := Round(255*(Angle/359));
      if TSLPSP.T <> Couleur.TSLPSP.T then
      begin
        DrawMark;
        Couleur.TSLPSP := TSLPSP;
        AffectModif;
        DrawPSP;
      end;
    end;
    CZPSPCarre : begin
      C_X := X;
      C_Y := Y;
      if C_X<PasCarre+RectPSP.Left then
        C_X:= PasCarre+RectPSP.Left
      else
      if C_X>PasCarre+RectPSP.Right then
        C_X:= PasCarre+RectPSP.Right;

      if C_Y<RectPSP.Top then
        C_Y:= RectPSP.Top
      else
      if C_Y>RectPSP.Bottom then
        C_Y:= RectPSP.Bottom;

      TSLPSP := Couleur.TSLPSP;
      TSLPSP.S := Round(255*((C_X-(PasCarre+RectPSP.Left))/(RectPSP.Right-RectPSP.Left)));
      TSLPSP.L := Round(255*((C_Y-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top)));
      DrawMark;
      Couleur.TSLPSP := TSLPSP;
      AffectModif;
      DrawCoul;
      DrawMark;
      CerclePSP.Repaint;
    end;
  end;
end;

procedure TFramePSP.CerclePSPMouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  TSLPSP : TTSLPSP;
  C_X,C_Y : Integer;
  Angle : Integer;
begin
  if mbLeft=Button then
  case ClickImg of
    CZPSPCercle : begin
      C_X := PasCarre+RectPSP.Left+(RectPSP.Right-RectPSP.Left)div 2;
      C_Y := RectPSP.Top+(RectPSP.Bottom-RectPSP.Top)div 2;;
      Angle := Round(LibAngle3Points(C_X,0,C_X,C_Y,X,Y));
      if Angle = 360 then
        Angle := 0;
      Angle := 359-Angle;
      TSLPSP := Couleur.TSLPSP;
      TSLPSP.T := Round(255*(Angle/359));
      if TSLPSP.T <> Couleur.TSLPSP.T then
      begin
        DrawMark;
        Couleur.TSLPSP := TSLPSP;
        AffectModif;
        DrawPSP;
      end;
    end;
    CZPSPCarre : begin
      C_X := X;
      C_Y := Y;
      if C_X<PasCarre+RectPSP.Left then
        C_X:= PasCarre+RectPSP.Left
      else
      if C_X>PasCarre+RectPSP.Right then
        C_X:= PasCarre+RectPSP.Right;

      if C_Y<RectPSP.Top then
        C_Y:= RectPSP.Top
      else
      if C_Y>RectPSP.Bottom then
        C_Y:= RectPSP.Bottom;

      TSLPSP := Couleur.TSLPSP;
      TSLPSP.S := Round(255*((C_X-(PasCarre+RectPSP.Left))/(RectPSP.Right-RectPSP.Left)));
      TSLPSP.L := Round(255*((C_Y-RectPSP.Top)/(RectPSP.Bottom-RectPSP.Top)));
      DrawMark;
      Couleur.TSLPSP := TSLPSP;
      AffectModif;
      DrawCoul;
      DrawMark;
      CerclePSP.Repaint;
    end;
  end;
  ClickImg := CZPSPnone;
end;

procedure TFramePSP.AffectModif;
begin
  //RVB
  SPRPSP.OnChange := nil;
  SPVPSP.OnChange := nil;
  SPBPSP.OnChange := nil;
  //TSL
  SPTPSP.OnChange := nil;
  SPSPSP.OnChange := nil;
  SPLPSP.OnChange := nil;
  //RVB
  SPRPSP.Value := Couleur.RVB.R;
  SPVPSP.Value := Couleur.RVB.V;
  SPBPSP.Value := Couleur.RVB.B;
  //TSL
  SPTPSP.Value := Couleur.TSLPSP.T;
  SPSPSP.Value := Couleur.TSLPSP.S;
  SPLPSP.Value := Couleur.TSLPSP.L;
  //RVB
  SPRPSP.Modified := true;
  SPVPSP.Modified := true;
  SPBPSP.Modified := true;
  //TSL
  SPTPSP.Modified := true;
  SPSPSP.Modified := true;
  SPLPSP.Modified := true;
  //RVB
  SPRPSP.OnChange := SPRVBPSPChange;
  SPVPSP.OnChange := SPRVBPSPChange;
  SPBPSP.OnChange := SPRVBPSPChange;
  //TSL
  SPTPSP.OnChange := SPTSLPSPChange;
  SPSPSP.OnChange := SPTSLPSPChange;
  SPLPSP.OnChange := SPTSLPSPChange;

  EHexaPSP.OnChange:=nil;
  EHexaPSP.Text := '$'+IntToHex(Couleur.Color,6);
  EHexaPSP.OnChange:=EHexaPSPChange;

  EHTMLPSP.OnChange:=nil;
  EHTMLPSP.Text := '#'+Couleur.HTML;
  EHTMLPSP.OnChange:=EHTMLPSPChange;
end;

procedure TFramePSP.MAJCoul;
begin
  AffectModif;
  DrawPSP;
end;

procedure TFramePSP.ImgCoulPSPMouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  Carre : HRGN;
begin
  Carre := CreateRectRgn(RectPreCol.Left,RectPreCol.Top,RectPreCol.Right,RectPreCol.Bottom);
  if PtInRegion(Carre,X,Y) then
  begin
    DrawMark;
    Couleur.Color := OldColor;
    AffectModif;
    DrawPSP;
  end;
end;

function HtmlToColor(Color: string): TColor;
begin
  Result := StringToColor('$' + Copy(Color, 6, 2) + Copy(Color, 4, 2) + Copy(Color, 2, 2));
end;

function HexToInt(HexStr: String): Int64;
var RetVar : Int64;
    i : byte;
begin
  HexStr := UpperCase(HexStr);
  if HexStr[length(HexStr)] = 'H' then
     Delete(HexStr,length(HexStr),1);
  RetVar := 0;

  for i := 1 to length(HexStr) do begin
      RetVar := RetVar shl 4;
      if HexStr[i] in ['0'..'9'] then
         RetVar := RetVar + (byte(HexStr[i]) - 48)
      else
         if HexStr[i] in ['A'..'F'] then
            RetVar := RetVar + (byte(HexStr[i]) - 55)
         else begin
            Retvar := 0;
            break;
         end;
  end;

  Result := RetVar;
end;

procedure TFramePSP.EHTMLPSPChange(Sender: TObject);
var
  s:string;
begin
  s:=EHTMLPSP.Text;
  if length(s)>0 then
    if s[1]='#' then delete(s,1,1);
  if length(s)=6 then begin
    SPRPSP.Value:=HexToInt(Copy(s, 1, 2));
    SPVPSP.Value:=HexToInt(Copy(s, 3, 2));
    SPBPSP.Value:=HexToInt(Copy(s, 5, 2));
  end;
end;

procedure TFramePSP.EHexaPSPChange(Sender: TObject);
var
  s:string;
begin
  s:=EHexaPSP.Text;
  if length(s)>0 then
    if s[1]='$' then delete(s,1,1);
  if length(s)=6 then begin
    SPRPSP.Value:=HexToInt(Copy(s, 5, 2));
    SPVPSP.Value:=HexToInt(Copy(s, 3, 2));
    SPBPSP.Value:=HexToInt(Copy(s, 1, 2));
  end;
end;

end.
