//--------------------------------------------------------------------------- #include #pragma hdrstop #include "PHLS.h" #include "math.h" #include "TClrUtil.hpp" #pragma package(smart_init) //--------------------------------------------------------------------------- // ValidCtrCheck is used to assure that the components created do not have // any pure virtual functions. // static inline void ValidCtrCheck(TPHLS *) { new TPHLS(NULL); } //--------------------------------------------------------------------------- ///// Private ///////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- void __fastcall TPHLS::CalculatePosition() { int uwid, uhei, k; if (FKind == HSeparation) { uwid = Width / 7; FCRect = Rect(0, 0, 3*uwid, 3*uwid); FTRect = Rect(4*uwid, 0, 7*uwid, 3*uwid); FWidth = 3*uwid; FHeight = FWidth; k = FWidth & 1; if (k) FRange = (FWidth-1) / 2; else FRange = (FWidth-2) / 2; } else if (FKind == VSeparation) { uhei = Height / 7; FCRect = Rect(0, 0, 3*uhei, 3*uhei); FTRect = Rect(0, 4*uhei, 3*uhei, 7*uhei); FWidth = 3*uhei; FHeight = FWidth; k = FHeight & 1; if (k) FRange = (FHeight-1) / 2; else FRange = (FHeight-2) / 2; } else { if (Width > Height) { k = Height & 1; if (k) FWidth = Height - 5; else FWidth = Height - 4; } else { k = Width & 1; if (k) FWidth = Width - 5; else FWidth = Width - 4; } FHeight = FWidth; FRange = FWidth / 2; FXLimit = FRange * 0.8; FRingSize = (FRange - FXLimit) / 2; FRingLength = FXLimit + FRingSize; k = (FXLimit / 2); FYLimit = sqrt(FXLimit * FXLimit - k * k) - 0.5; FWid = (FRange - FXLimit)+(FXLimit / 2); FSlope = (double) FYLimit / (FRange + FXLimit - FWid); FYAbs = (FSlope * FWid - (FRange - FYLimit)) + FRange; FCRect = Rect(2, 2, FHeight+2, FHeight+2); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetPosition() { Canvas->CopyMode = cmSrcCopy; if (FKind == HSeparation) { Canvas->CopyRect(FCRect, Circle->Canvas, Rect(0, 0, FWidth, FHeight)); Canvas->CopyRect(FTRect, Triangle->Canvas, Rect(0, 0, FWidth, FHeight)); } else if (FKind == VSeparation) { Canvas->CopyRect(FCRect, Circle->Canvas, Rect(0, 0, FWidth, FHeight)); Canvas->CopyRect(FTRect, Triangle->Canvas, Rect(0, 0, FWidth, FHeight)); } else { Canvas->CopyRect(FCRect, Circle->Canvas, Rect(0, 0, FWidth, FHeight)); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetColor(TColor Value) { double h, l, s; if (FColor != Value) { FColor = Value; Frgb.rgbRed = 0xFF & Value; Frgb.rgbGreen = 0xFF & (Value>>8); Frgb.rgbBlue = 0xFF & (Value>>16); RGBQUAD2HLS(Frgb, h, l, s); if ((l!=0)&&(s!=0)) { FHue = h; FLig = l*100; FSat = s*100; } else if (s==0) { FSat = 0; FLig = l*100; } if (l==0) FLig = 0; } if (FOnColorChange) FOnColorChange(this); if (FOnHueChange) FOnHueChange(this); if (FOnLigChange) FOnLigChange(this); if (FOnSatChange) FOnSatChange(this); Refresh(); } //--------------------------------------------------------------------------- void __fastcall TPHLS::ChangeColor() { Frgb = HLS2RGBQUAD((double)FHue, FLig/100.0, FSat/100.0); FColor = HLS2TColor((double)FHue, FLig/100.0, FSat/100.0); if (FOnColorChange) FOnColorChange(this); } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetHue(int Value) { if (FHue != Value) { if (Value < 0) FHue = 0; else if (Value > 360) FHue = 359; else FHue = Value; Refresh(); if (FOnHueChange) FOnHueChange(this); ChangeColor(); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetLig(int Value) { if (FLig != Value) { if (Value < 0) FLig = 0; else if (Value > 100) FLig = 100; else FLig = Value; FLig = Value; Refresh(); if (FOnLigChange) FOnLigChange(this); ChangeColor(); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetSat(int Value) { if (FSat != Value) { if (Value < 0) FSat = 0; else if (Value > 100) FSat = 100; else FSat = Value; FSat = Value; Refresh(); if (FOnSatChange) FOnSatChange(this); ChangeColor(); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::SetHLSKind(TKindHLS Value) { if (FKind != Value) { FKind = Value; Canvas->Brush->Color = clBtnFace; Canvas->FillRect(Rect(0, 0, Width, Height)); Refresh(); } } //-------------------------------------------------------------------------- void __fastcall TPHLS::PaintHLS() { if (FKind == HSeparation || FKind == VSeparation) { Circle->PixelFormat = pf24bit; Circle->Width = FWidth; Circle->Height = FHeight; Circle->Canvas->Brush->Color = clBtnFace; Circle->Canvas->FillRect(Rect(0, 0, FWidth, FHeight)); CDrawHS(); Circle->Canvas->Pen->Mode = pmXor; Circle->Canvas->Pen->Color = clWhite; CDrawHSBar(FHue, FSat); Triangle->PixelFormat = pf24bit; Triangle->Width = FWidth; Triangle->Height = FHeight; Triangle->Canvas->Brush->Color = clBtnFace; Triangle->Canvas->FillRect(Rect(0, 0, FWidth, FHeight)); CDrawL(); Triangle->Canvas->Pen->Mode = pmXor; Triangle->Canvas->Pen->Color = clWhite; CDrawLBar(FLig); } else { Circle->PixelFormat = pf24bit; Circle->Width = FWidth; Circle->Height = FHeight; Circle->Canvas->Brush->Color = clBtnFace; Circle->Canvas->FillRect(Rect(0, 0, FWidth, FHeight)); Draw_Circle(); Draw_TriAngle(FHue); Circle->Canvas->Pen->Mode = pmXor; Circle->Canvas->Pen->Color = clWhite; Draw_RingPoint(FHue); Draw_TPoint(FSat, FLig); } } //--------------------------------------------------------------------------- void __fastcall TPHLS::Draw_Circle() { double h, l, s, sqtval; Byte r, g, b; int x, y, xx, sol, lim; Byte *sh; l = 0.5; s = 1; sqtval = FRange * FRange; for (y=-FRange; yScanLine[y+FRange]; sol = sqrt(sqtval-y*y); for (x=-sol; x<=sol; x++) { lim = sqrt(x*x+y*y); if (limScanLine[FRange+y]; sl2 = (Byte*) Circle->ScanLine[FRange-y]; sol =((FYAbs-y) / FSlope)-FWid; for (x=0; x<=sol; x++) { xx = 3*(x+FWid); if (sol==0) s = 0; else s = x/sol; l = (FYLimit-y)/(2*FYLimit); HLS2RGB(h, l, s, r, g, b); *(sl1+xx) = b; *(sl1+xx+1) = g; *(sl1+xx+2) = r; l =(FYLimit+y)/(2*FYLimit); HLS2RGB(h, l, s, r, g, b); *(sl2+xx) = b; *(sl2+xx+1) = g; *(sl2+xx+2) = r; } } } //-------------------------------------------------------------------------- void __fastcall TPHLS::Draw_RingPoint(int Angle) { double h; int size = FRingSize / 2; h = M_PI*Angle/180; Circle->Canvas->Ellipse((FRange - size)+(cos(h)*FRingLength), (FRange - size)-(sin(h)*FRingLength), (FRange + size)+(cos(h)*FRingLength), (FRange + size)-(sin(h)*FRingLength)); } //-------------------------------------------------------------------------- void __fastcall TPHLS::Draw_TPoint(int S, int L) { int Y1, sol, Y, X; int size = FRingSize / 2; Y = (FRange + FYLimit)-(L*(FYLimit * 2)/100); Y1 = abs(Y-FRange); sol =((FYAbs-Y1) / FSlope )-FWid; X = (sol*S/100)+FWid; Circle->Canvas->Ellipse(X-size, Y-size, X+size, Y+size); } //-------------------------------------------------------------------------- void __fastcall TPHLS::Change_HS(int X, int Y) { int H; X = X-FRange; Y = Y-FRange; if (Y<0) H = (180*atan2(-Y, X)/M_PI); else H = 180+(180*atan2(Y, -X)/M_PI); FHue = H; } //-------------------------------------------------------------------------- void __fastcall TPHLS::Change_LS(int X, int Y) { int lim, S, L; X = X-(FWid); Y = Y-(FRange - FYLimit); L = 100*((FYLimit * 2)-Y)/(FYLimit * 2); if (L < 0) FLig = 0; else if (L > 100) FLig = 100; else FLig = L; Y = abs(Y-FYLimit); lim = (FYLimit-Y) / FSlope; if (lim==0) S = 0; else S = 100*X/lim; if (S < 0) FSat = 0; else if (S > 100) FSat = 100; else FSat = S; } //-------------------------------------------------------------------------- void __fastcall TPHLS::CDrawHS() { int x, y, v, xx, sqRange; double h, l, s; Byte r, g, b; Byte *sl, *sh; l = 0.5; sqRange = FRange*FRange; for (y=0; yScanLine[FRange-y]; sh = (Byte *) Circle->ScanLine[FRange+y]; v = sqrt(sqRange - y*y); for (x=-v; x<=v; x++) { xx = 3*(FRange+x); s = sqrt(x*x + y*y)/FRange; if ((y==0) && (x==0)) h = 0; else h = atan2(y, x)*180/M_PI; HLS2RGB(h, l, s, r, g, b); *(sl+xx) = b; *(sl+xx+1) = g; *(sl+xx+2) = r; if ((y==0) && (x==0)) h = 180; else h = 180 + atan2(y, -x) * 180 / M_PI; HLS2RGB(h, l, s, r, g, b); *(sh+xx) = b; *(sh+xx+1) = g; *(sh+xx+2) = r; } } } //--------------------------------------------------------------------------- void __fastcall TPHLS::CDrawL() { int x, y, v, xx; double h, l, s; Byte r, g, b; Byte *sl, *sh; h = FHue; for (y=0; y<=FRange; y++) { sl = (Byte *) Triangle->ScanLine[FRange-y]; sh = (Byte *) Triangle->ScanLine[FRange+y]; v = 2*(FRange-y); for (x=0; x<=v; x++) { xx = 3*x; if (v==0) s = 0; else s = (double) x/v; l = 0.5+ y/(2.0*FRange); HLS2RGB(h, l, s, r, g, b); *(sl+xx) = b; *(sl+xx+1) = g; *(sl+xx+2) = r; l = 0.5-y/(2.0*FRange); HLS2RGB(h, l, s, r, g, b); *(sh+xx) = b; *(sh+xx+1) = g; *(sh+xx+2) = r; } } } //--------------------------------------------------------------------------- void __fastcall TPHLS::CDrawHSBar(int h, int s) { double r, x, y; int cx, cy; r = h*M_PI/180; Circle->Canvas->MoveTo(FRange, FRange); x = FRange * cos(r); y = FRange * sin(r); Circle->Canvas->LineTo(FRange+(int)x, FRange-(int)y); cx = FRange + (x*s/100); cy = FRange - (y*s/100); Circle->Canvas->Rectangle(cx-2, cy-2, cx+2, cy+2); } //--------------------------------------------------------------------------- void __fastcall TPHLS::CDrawLBar(int l) { int y; y = (2*FRange)-l*(2*FRange) / 100; Triangle->Canvas->MoveTo(0, y); Triangle->Canvas->LineTo((2.0*FRange), y); } //--------------------------------------------------------------------------- void __fastcall TPHLS::CMoveHS(int X, int Y) { int h, s; X = X-FRange; Y = Y-FRange; if (Y<0) h = atan2(-Y, X)*180/M_PI; else { if ((Y==0) && (X==0)) h = 180; else h = 180+atan2(Y, -X)*180/M_PI; } FHue = h; s = 100*sqrt(X*X+Y*Y)/FRange; if (s>100) s = 100; FSat = s; } //--------------------------------------------------------------------------- void __fastcall TPHLS::CMoveL(int Y) { int l; l = 100-100*Y / (2.0*FRange); if (l<0) l = 0; if (l>100) l =100; FLig = l; } //--------------------------------------------------------------------------- void __fastcall TPHLS::CRunHLS() { double h, l, s; h = (double) FHue; l = (double) FLig/100; s = (double) FSat/100; Frgb = HLS2RGBQUAD(h, l, s); } //--------------------------------------------------------------------------- ///// Protected ///////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- void __fastcall TPHLS::Paint() { CalculatePosition(); PaintHLS(); SetPosition(); } //--------------------------------------------------------------------------- ///// Public ///////////////////////////////////////////////////////////// //--------------------------------------------------------------------------- __fastcall TPHLS::TPHLS(TComponent* Owner) : TGraphicControl(Owner) { ControlStyle = ControlStyle << csOpaque; Width = 300; Height = 200; Circle = new Graphics::TBitmap; Triangle = new Graphics::TBitmap; FHue = 0; FLig = 0; FSat = 0; HS = LS = false; } //--------------------------------------------------------------------------- __fastcall TPHLS::~TPHLS() { delete Circle; delete Triangle; } //--------------------------------------------------------------------------- void __fastcall TPHLS::WMLBUTTONDOWN(TMessage &msg) { POINT p = Point(msg.LParamLo, msg.LParamHi); if (FKind == Union) { if (PtInRect(&FCRect, p)) { double r = sqrt((p.x-FRange-2)*(p.x-FRange-2)+(p.y-FRange-2)*(p.y-FRange-2)); if ((r>=FXLimit)&&(r<=FRange)) { HS = true; LS = false; } else if (r=FXLimit)&&(r<=FRange)) { if (HS) Change_HS(p.x-2, p.y-2); if (FOnHueChange) FOnHueChange(this); } else if (r