{----------------------------------------------------------------------------- The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/MPL-1.1.html Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is: ColorSpaces.pas, released on 2004-09-11. The Initial Developer of the Original Code is Florent Ouchet [ouchet dott florent att laposte dott net] Portions created by Florent Ouchet are Copyright (C) 2004 Florent Ouchet. All Rights Reserved. Contributor(s): - You may retrieve the latest version of this file at the Project JEDI's JVCL home page, located at http://jvcl.sourceforge.net Known Issues: -----------------------------------------------------------------------------} // $Id: JvFullColorSpaces.pas 11104 2006-12-29 17:55:15Z marquardt $ // TColorBox is implemented in ExtCtrls in Delphi and BCB version 6 and + unit JvFullColorSpaces; {$I jvcl.inc} interface uses {$IFDEF UNITVERSIONING} JclUnitVersioning, {$ENDIF UNITVERSIONING} Windows, Classes, SysUtils, Graphics, JvTypes; type TJvAxisIndex = (axIndex0, axIndex1, axIndex2); TJvFullColorSpaceID = type Byte; TJvFullColor = type Cardinal; const JvSystemColorMask = {$IFDEF COMPILER7_UP} clSystemColor; {$ELSE} $80000000; {$ENDIF} JvSubFullColorMask = $03000000; JvSystemFullColorMask = $01000000; JvSpecialFullColorMask = $03000000; const csRGB = TJvFullColorSpaceID(1 shl 2); csHLS = TJvFullColorSpaceID(2 shl 2); csCMY = TJvFullColorSpaceID(3 shl 2); csYUV = TJvFullColorSpaceID(4 shl 2); csHSV = TJvFullColorSpaceID(5 shl 2); csYIQ = TJvFullColorSpaceID(6 shl 2); csYCC = TJvFullColorSpaceID(7 shl 2); csXYZ = TJvFullColorSpaceID(8 shl 2); csLAB = TJvFullColorSpaceID(9 shl 2); csDEF = TJvFullColorSpaceID(10 shl 2); csID_MASK = $FC; csMIN = $04 and csID_MASK; csMAX = $FF and csID_MASK; RGB_MIN = 0; RGB_MAX = 255; HLS_MIN = 0; HLS_MAX = 240; CMY_MIN = 0; CMY_MAX = 255; YUV_MIN = 16; YUV_MAX = 235; HSV_MIN = 0; HSV_MAX = 240; YIQ_MIN = 0; YIQ_MAX = 255; YCC_MIN = 0; YCC_MAX = 255; XYZ_MIN = 0; XYZ_MAX = 255; LAB_MIN = 0; LAB_MAX = 255; DEF_MIN = 0; DEF_MAX = 255; fclRGBBlack = TJvFullColor((Ord(csRGB) shl 24) or $000000); fclRGBWhite = TJvFullColor((Ord(csRGB) shl 24) or $FFFFFF); fclRGBRed = TJvFullColor((Ord(csRGB) shl 24) or $0000FF); fclRGBLime = TJvFullColor((Ord(csRGB) shl 24) or $00FF00); fclRGBBlue = TJvFullColor((Ord(csRGB) shl 24) or $FF0000); fclDEFWindowText = TJvFullColor((Ord(csDEF) shl 24) or JvSystemFullColorMask or COLOR_WINDOWTEXT); type TJvColorSpace = class(TPersistent) private FID: TJvFullColorSpaceID; protected function GetAxisName(Index: TJvAxisIndex): string; virtual; function GetAxisMin(Index: TJvAxisIndex): Byte; virtual; function GetAxisMax(Index: TJvAxisIndex): Byte; virtual; function GetAxisDefault(Index: TJvAxisIndex): Byte; virtual; function GetName: string; virtual; function GetShortName: string; virtual; function GetNumberOfColors: Cardinal; virtual; public constructor Create(ColorID: TJvFullColorSpaceID); virtual; function ConvertFromColor(AColor: TColor): TJvFullColor; virtual; function ConvertToColor(AColor: TJvFullColor): TColor; virtual; property ID: TJvFullColorSpaceID read FID; property NumberOfColors: Cardinal read GetNumberOfColors; property Name: string read GetName; property ShortName: string read GetShortName; property AxisName[Index: TJvAxisIndex]: string read GetAxisName; property AxisMin[Index: TJvAxisIndex]: Byte read GetAxisMin; property AxisMax[Index: TJvAxisIndex]: Byte read GetAxisMax; property AxisDefault[Index: TJvAxisIndex]: Byte read GetAxisDefault; end; {TJvColorConversionMatrix = array[0..3,0..3] of Extended; // OpenGL and D3D style matrix PJvColorConversionMatrix = ^TJvColorConversionMatrix; TJvMatrixType = (mtFromRGB, mtToRGB); TJvMatrixColorSpace = class(TJvColorSpace) protected FToRGBMatrix, FFromRGBMatrix: TJvColorConversionMatrix; public constructor Create(ColorID: TJvFullColorSpaceID; AMatrix: PJvColorConversionMatrix; MatrixType: TJvMatrixType); reintroduce; destructor Destroy; override; function ConvertToID(AFullColor: TJvFullColor; NewID: TJvFullColorSpaceID; // RGBToNewIDMatrix: PJvColorConversionMatrix): TJvFullColor; // use a call with pointer argument function ConvertFromID(AFullColor: TJvFullColor; OldID: TJvFullColorSpaceID; // because a matrix is 160 Bytes !!! OldIDToRGBMatrix: PJvColorConversionMatrix): TJvFullColor; // /!\ not on the stack /!\ function ConvertFromColor(AColor: TColor): TColor; override; // function ConvertToColor(AColor: TJvFullColor): TColor; override; function GetToRGBMatrix: PJvColorConversionMatrix; function GetFromRGBMatrix: PJvColorConversionMatrix; end;} TJvRGBColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvHLSColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvCMYColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvYUVColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvHSVColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvYIQColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvYCCColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvXYZColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvLABColorSpace = class(TJvColorSpace) protected function GetAxisName(Index: TJvAxisIndex): string; override; function GetAxisMin(Index: TJvAxisIndex): Byte; override; function GetAxisMax(Index: TJvAxisIndex): Byte; override; function GetName: string; override; function GetShortName: string; override; function GetAxisDefault(Index: TJvAxisIndex): Byte; override; public function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; end; TJvDEFColorSpace = class(TJvColorSpace) private FDelphiColors: TStringList; procedure GetColorValuesCallBack(const S: string); protected function GetName: string; override; function GetShortName: string; override; function GetNumberOfColors: Cardinal; override; function GetColorName(Index: Integer): string; function GetPrettyName(Index: Integer): string; function GetColorValue(Index: Integer): TColor; public constructor Create(ColorID: TJvFullColorSpaceID); override; destructor Destroy; override; function ConvertFromColor(AColor: TColor): TJvFullColor; override; function ConvertToColor(AColor: TJvFullColor): TColor; override; procedure AddCustomColor(AColor: TColor; ShortName: string; PrettyName: string); procedure AddDelphiColor(Value: TColor); property ColorCount: Cardinal read GetNumberOfColors; property ColorName[Index: Integer]: string read GetColorName; property ColorPrettyName[Index: Integer]: string read GetPrettyName; property ColorValue[Index: Integer]: TColor read GetColorValue; default; end; TJvColorSpaceManager = class(TPersistent) private FColorSpaceList: TList; function GetCount: Integer; function GetColorSpaceByIndex(Index: Integer): TJvColorSpace; protected function GetColorSpace(ID: TJvFullColorSpaceID): TJvColorSpace; virtual; public procedure RegisterColorSpace(NewColorSpace: TJvColorSpace); procedure UnRegisterColorSpace(AColorSpace: TJvColorSpace); constructor Create; destructor Destroy; override; function ConvertToID(AColor: TJvFullColor; DestID: TJvFullColorSpaceID): TJvFullColor; function ConvertToColor(AColor: TJvFullColor): TColor; function ConvertFromColor(AColor: TColor): TJvFullColor; function GetColorSpaceID(AColor: TJvFullColor): TJvFullColorSpaceID; property ColorSpace[ID: TJvFullColorSpaceID]: TJvColorSpace read GetColorSpace; property ColorSpaceByIndex[Index: Integer]: TJvColorSpace read GetColorSpaceByIndex; property Count: Integer read GetCount; end; EJvColorSpaceError = class(EJVCLException); function ColorSpaceManager: TJvColorSpaceManager; function GetAxisValue(AColor: TJvFullColor; AAxis: TJvAxisIndex): Byte; function SetAxisValue(AColor: TJvFullColor; AAxis: TJvAxisIndex; NewValue: Byte): TJvFullColor; procedure SplitColorParts(AColor: TJvFullColor; var Part1, Part2, Part3: Integer); function JoinColorParts(const Part1, Part2, Part3: Integer): TJvFullColor; {$IFDEF UNITVERSIONING} const UnitVersioning: TUnitVersionInfo = ( RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_32/run/JvFullColorSpaces.pas $'; Revision: '$Revision: 11104 $'; Date: '$Date: 2006-12-29 18:55:15 +0100 (ven., 29 déc. 2006) $'; LogPath: 'JVCL\run' ); {$ENDIF UNITVERSIONING} implementation uses {$IFDEF COMPILER6_UP} Controls, StdCtrls, ExtCtrls, {$ENDIF COMPILER6_UP} JvResources, TypInfo, JvJCLUtils ,JvJVCLUtils, JclMath; var GlobalColorSpaceManager: TJvColorSpaceManager = nil; const HLS_MAX_HALF = HLS_MAX / 2.0; HLS_MAX_ONE_THIRD = HLS_MAX / 3.0; HLS_MAX_TWO_THIRDS = (HLS_MAX * 2.0) / 3.0; HLS_MAX_SIXTH = HLS_MAX / 6.0; HLS_MAX_TWELVETH = HLS_MAX / 12.0; function ColorSpaceManager: TJvColorSpaceManager; begin if GlobalColorSpaceManager = nil then begin GlobalColorSpaceManager := TJvColorSpaceManager.Create; GlobalColorSpaceManager.RegisterColorSpace(TJvRGBColorSpace.Create(csRGB)); GlobalColorSpaceManager.RegisterColorSpace(TJvHLSColorSpace.Create(csHLS)); GlobalColorSpaceManager.RegisterColorSpace(TJvCMYColorSpace.Create(csCMY)); GlobalColorSpaceManager.RegisterColorSpace(TJvYUVColorSpace.Create(csYUV)); GlobalColorSpaceManager.RegisterColorSpace(TJvHSVColorSpace.Create(csHSV)); GlobalColorSpaceManager.RegisterColorSpace(TJvYIQColorSpace.Create(csYIQ)); GlobalColorSpaceManager.RegisterColorSpace(TJvYCCColorSpace.Create(csYCC)); GlobalColorSpaceManager.RegisterColorSpace(TJvXYZColorSpace.Create(csXYZ)); GlobalColorSpaceManager.RegisterColorSpace(TJvLABColorSpace.Create(csLAB)); GlobalColorSpaceManager.RegisterColorSpace(TJvDEFColorSpace.Create(csDEF)); end; Result := GlobalColorSpaceManager; end; function SetAxisValue(AColor: TJvFullColor; AAxis: TJvAxisIndex; NewValue: Byte): TJvFullColor; begin case AAxis of axIndex0: AColor := (AColor and $FFFFFF00) or NewValue; axIndex1: AColor := (AColor and $FFFF00FF) or (NewValue shl 8); axIndex2: AColor := (AColor and $FF00FFFF) or (NewValue shl 16); end; Result := AColor; end; function GetAxisValue(AColor: TJvFullColor; AAxis: TJvAxisIndex): Byte; begin case AAxis of axIndex0: Result := (AColor and $000000FF); axIndex1: Result := (AColor and $0000FF00) shr 8; axIndex2: Result := (AColor and $00FF0000) shr 16; else Result := 0; end; end; procedure SplitColorParts(AColor: TJvFullColor; var Part1, Part2, Part3: Integer); begin Part1 := AColor and $000000FF; Part2 := (AColor shr 8) and $000000FF; Part3 := (AColor shr 16) and $000000FF; end; function JoinColorParts(const Part1, Part2, Part3: Integer): TJvFullColor; begin Result := (Part1 and $000000FF) or ((Part2 and $000000FF) shl 8) or ((Part3 and $000000FF) shl 16); end; //=== { TJvColorSpace } ====================================================== constructor TJvColorSpace.Create(ColorID: TJvFullColorSpaceID); begin inherited Create; if (ColorID >= csMIN) and (ColorID <= csMAX) then FID := ColorID else raise EJvColorSpaceError.CreateResFmt(@RsEIllegalID, [Ord(ColorID)]); end; function TJvColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; begin Result := (AColor and $00FFFFFF) or (ID shl 24); end; function TJvColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; begin Result := AColor and $00FFFFFF; end; function TJvColorSpace.GetNumberOfColors: Cardinal; begin Result := (AxisMax[axIndex0] - AxisMin[axIndex0] + 1) * (AxisMax[axIndex1] - AxisMin[axIndex1] + 1) * (AxisMax[axIndex2] - AxisMin[axIndex2] + 1); end; function TJvColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := Low(Byte); end; function TJvColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := High(Byte); end; function TJvColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := Low(Byte); end; function TJvColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin Result := RsEUnnamedAxis; end; function TJvColorSpace.GetName: string; begin Result := RsEUnnamedSpace; end; function TJvColorSpace.GetShortName: string; begin Result := RsEUCS; end; //=== { TJvRGBColorSpace } =================================================== function TJvRGBColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; begin Result := inherited ConvertFromColor(AColor); end; function TJvRGBColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; begin Result := inherited ConvertToColor(AColor); end; function TJvRGBColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 0; end; function TJvRGBColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := RGB_MAX; end; function TJvRGBColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := RGB_MIN; end; function TJvRGBColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsRGB_Red; axIndex1: Result := RsRGB_Green; axIndex2: Result := RsRGB_Blue; else Result := inherited GetAxisName(Index); end; end; function TJvRGBColorSpace.GetName: string; begin Result := RsRGB_FullName; end; function TJvRGBColorSpace.GetShortName: string; begin Result := RsRGB_ShortName; end; //=== { TJvHLSColorSpace } =================================================== function TJvHLSColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Hue, Lightness, Saturation: Double; Red, Green, Blue: Integer; ColorMax, ColorMin, ColorDiff, ColorSum: Double; RedDelta, GreenDelta, BlueDelta: Extended; begin SplitColorParts(AColor, Red, Green, Blue); if Red > Green then ColorMax := Red else ColorMax := Green; if Blue > ColorMax then ColorMax := Blue; if Red < Green then ColorMin := Red else ColorMin := Green; if Blue < ColorMin then ColorMin := Blue; ColorDiff := ColorMax - ColorMin; ColorSum := ColorMax + ColorMin; Lightness := (ColorSum * HLS_MAX + RGB_MAX) / (2.0 * RGB_MAX); if ColorMax = ColorMin then AColor := (Round(Lightness) shl 8) or (2 * HLS_MAX div 3) else begin if Lightness <= HLS_MAX_HALF then Saturation := (ColorDiff * HLS_MAX + ColorSum / 2.0) / ColorSum else Saturation := (ColorDiff * HLS_MAX + ((2.0 * RGB_MAX - ColorMax - ColorMin) / 2.0)) / (2.0 * RGB_MAX - ColorMax - ColorMin); RedDelta := ((ColorMax - Red) * HLS_MAX_SIXTH + ColorDiff / 2.0) / ColorDiff; GreenDelta := ((ColorMax - Green) * HLS_MAX_SIXTH + ColorDiff / 2.0) / ColorDiff; BlueDelta := ((ColorMax - Blue) * HLS_MAX_SIXTH + ColorDiff / 2.0) / ColorDiff; if Red = ColorMax then Hue := BlueDelta - GreenDelta else if Green = ColorMax then Hue := HLS_MAX_ONE_THIRD + RedDelta - BlueDelta else Hue := 2.0 * HLS_MAX_ONE_THIRD + GreenDelta - RedDelta; if Hue < 0 then Hue := Hue + HLS_MAX; if Hue > HLS_MAX then Hue := Hue - HLS_MAX; AColor := JoinColorParts(Cardinal(Round(Hue)), Cardinal(Round(Lightness)), Cardinal(Round(Saturation))); end; Result := inherited ConvertFromColor(AColor); end; function TJvHLSColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Double; Magic1, Magic2: Double; Hue, Lightness, Saturation: Integer; function HueToRGB(Lightness, Saturation, Hue: Double): Integer; var ResultEx: Double; begin if Hue < 0 then Hue := Hue + HLS_MAX; if Hue > HLS_MAX then Hue := Hue - HLS_MAX; if Hue < HLS_MAX_SIXTH then ResultEx := Lightness + ((Saturation - Lightness) * Hue + HLS_MAX_TWELVETH) / HLS_MAX_SIXTH else if Hue < HLS_MAX_HALF then ResultEx := Saturation else if Hue < HLS_MAX_TWO_THIRDS then ResultEx := Lightness + ((Saturation - Lightness) * (HLS_MAX_TWO_THIRDS - Hue) + HLS_MAX_TWELVETH) / HLS_MAX_SIXTH else ResultEx := Lightness; Result := Round(ResultEx); end; function RoundColor(Value: Double): Integer; begin if Value > RGB_MAX then Result := RGB_MAX else Result := Round(Value); end; begin SplitColorParts(AColor, Hue, Lightness, Saturation); if Saturation = 0 then begin Red := (Lightness * RGB_MAX) / HLS_MAX; Green := Red; Blue := Red; end else begin if Lightness <= HLS_MAX_HALF then Magic2 := (Lightness * (HLS_MAX + Saturation) + HLS_MAX_HALF) / HLS_MAX else Magic2 := Lightness + Saturation - ((Lightness * Saturation) + HLS_MAX_HALF) / HLS_MAX; Magic1 := 2 * Lightness - Magic2; Red := (HueToRGB(Magic1, Magic2, Hue + HLS_MAX_ONE_THIRD) * RGB_MAX + HLS_MAX_HALF) / HLS_MAX; Green := (HueToRGB(Magic1, Magic2, Hue) * RGB_MAX + HLS_MAX_HALF) / HLS_MAX; Blue := (HueToRGB(Magic1, Magic2, Hue - HLS_MAX_ONE_THIRD) * RGB_MAX + HLS_MAX_HALF) / HLS_MAX; end; Result := inherited ConvertToColor( JoinColorParts(RoundColor(Red), RoundColor(Green), RoundColor(Blue))); end; function TJvHLSColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 120; end; function TJvHLSColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := HLS_MAX; end; function TJvHLSColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := HLS_MIN; end; function TJvHLSColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsHLS_Hue; axIndex1: Result := RsHLS_Lightness; axIndex2: Result := RsHLS_Saturation; else Result := inherited GetAxisName(Index); end; end; function TJvHLSColorSpace.GetName: string; begin Result := RsHLS_FullName; end; function TJvHLSColorSpace.GetShortName: string; begin Result := RsHLS_ShortName; end; //=== { TJvCMYColorSpace } =================================================== function TJvCMYColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Red, Green, Blue: Integer; Cyan, Magenta, Yellow: Integer; begin SplitColorParts(AColor, Red, Green, Blue); Cyan := ((RGB_MAX - Red ) * (CMY_MAX-CMY_MIN+1) div (RGB_MAX-RGB_MIN+1)) + CMY_MIN; Magenta := ((RGB_MAX - Green) * (CMY_MAX-CMY_MIN+1) div (RGB_MAX-RGB_MIN+1)) + CMY_MIN; Yellow := ((RGB_MAX - Blue ) * (CMY_MAX-CMY_MIN+1) div (RGB_MAX-RGB_MIN+1)) + CMY_MIN; Result := inherited ConvertFromColor(JoinColorParts(Cyan, Magenta, Yellow)); end; function TJvCMYColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Cyan, Magenta, Yellow: Integer; Red, Green, Blue: Integer; begin SplitColorParts(AColor, Cyan, Magenta, Yellow); Red := ((CMY_MAX - Cyan ) * (RGB_MAX-RGB_MIN+1) div (CMY_MAX-CMY_MIN+1)) + RGB_MIN; Green := ((CMY_MAX - Magenta) * (RGB_MAX-RGB_MIN+1) div (CMY_MAX-CMY_MIN+1)) + RGB_MIN; Blue := ((CMY_MAX - Yellow ) * (RGB_MAX-RGB_MIN+1) div (CMY_MAX-CMY_MIN+1)) + RGB_MIN; Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvCMYColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 255; end; function TJvCMYColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := CMY_MAX; end; function TJvCMYColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := CMY_MIN; end; function TJvCMYColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsCMY_Cyan; axIndex1: Result := RsCMY_Magenta; axIndex2: Result := RsCMY_Yellow; else Result := inherited GetAxisName(Index); end; end; function TJvCMYColorSpace.GetName: string; begin Result := RsCMY_FullName; end; function TJvCMYColorSpace.GetShortName: string; begin Result := RsCMY_ShortName; end; //=== { TJvYUVColorSpace } =================================================== function TJvYUVColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Y, U, V: Integer; Red, Green, Blue: Integer; begin SplitColorParts(AColor, Red, Green, Blue); Y := Round(0.257*Red + 0.504*Green + 0.098*Blue) + 16; V := Round(0.439*Red - 0.368*Green - 0.071*Blue) + 128; U := Round(-0.148*Red - 0.291*Green + 0.439*Blue) + 128; Y := EnsureRange(Y, YUV_MIN, YUV_MAX); U := EnsureRange(U, YUV_MIN, YUV_MAX); V := EnsureRange(V, YUV_MIN, YUV_MAX); Result := inherited ConvertFromColor(JoinColorParts(Y, U, V)); end; function TJvYUVColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Integer; Y, U, V: Integer; begin SplitColorParts(AColor, Y, U, V); Y := Y - 16; U := U - 128; V := V - 128; Red := Round(1.164*Y - 0.002*U + 1.596*V); Green := Round(1.164*Y - 0.391*U - 0.813*V); Blue := Round(1.164*Y + 2.018*U - 0.001*V); Red := EnsureRange(Red , RGB_MIN, RGB_MAX); Green := EnsureRange(Green, RGB_MIN, RGB_MAX); Blue := EnsureRange(Blue, RGB_MIN, RGB_MAX); Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvYUVColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 128; end; function TJvYUVColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := YUV_MAX; end; function TJvYUVColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := YUV_MIN; end; function TJvYUVColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsYUV_Y; axIndex1: Result := RsYUV_U; axIndex2: Result := RsYUV_V; else Result := inherited GetAxisName(Index); end; end; function TJvYUVColorSpace.GetName: string; begin Result := RsYUV_FullName; end; function TJvYUVColorSpace.GetShortName: string; begin Result := RsYUV_ShortName; end; //=== { TJvHSVColorSpace } =================================================== function TJvHSVColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Hue, Saturation, Value: Integer; Red, Green, Blue: Integer; ColorMax, ColorMin, ColorDelta: Integer; begin SplitColorParts(AColor, Red, Green, Blue); if Red > Green then ColorMax := Red else ColorMax := Green; if Blue > ColorMax then ColorMax := Blue; if Red < Green then ColorMin := Red else ColorMin := Green; if Blue < ColorMin then ColorMin := Blue; ColorDelta := ColorMax - ColorMin; Value := ColorMax; if Value = 0 then Saturation := 0 else Saturation := (255 * ColorDelta) div Value; if Saturation = 0 then Hue := 0 else begin Hue := 0; if Value = Red then Hue := (40 * (Green - Blue) div ColorDelta); if Value = Green then Hue := (HSV_MAX div 3) + (40 * (Blue - Red) div ColorDelta); if Value = Blue then Hue := ((HSV_MAX * 2) div 3) + (40 * (Red - Green) div ColorDelta); end; if Hue < 0 then Hue := Hue + HSV_MAX; if Hue > HSV_MAX then Hue := Hue - HSV_MAX; Result := inherited ConvertFromColor(JoinColorParts(Hue, Saturation, Value)); end; function TJvHSVColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Hue, Saturation, Value: Integer; Red, Green, Blue: Integer; P, Q, T, Summ, Rest: Integer; begin SplitColorParts(AColor, Hue, Saturation, Value); if Saturation = 0 then begin Red := Value; Green := Value; Blue := Value; end else begin if Hue = HSV_MAX then Hue := 0; Rest := Hue mod (HSV_MAX div 6); Hue := Hue div (HSV_MAX div 6); Summ := Value * Saturation; P := Value - Summ div RGB_MAX; Q := Value - (Summ * Rest) div (RGB_MAX * (HSV_MAX div 6)); T := Value - (Summ * ((HSV_MAX div 6) - Rest)) div (RGB_MAX * (HSV_MAX div 6)); case Hue of 0: begin Red := Value; Green := T; Blue := P; end; 1: begin Red := Q; Green := Value; Blue := P; end; 2: begin Red := P; Green := Value; Blue := T; end; 3: begin Red := P; Green := Q; Blue := Value; end; 4: begin Red := T; Green := P; Blue := Value; end; else Red := Value; Green := P; Blue := Q; end; end; Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvHSVColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin case Index of axIndex0: Result := 120; axIndex1: Result := 240; else Result := 150; end; end; function TJvHSVColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin case Index of axIndex0: Result := HSV_MAX; else Result := RGB_MAX; end; end; function TJvHSVColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := HSV_MIN; end; function TJvHSVColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsHSV_Hue; axIndex1: Result := RsHSV_Saturation; axIndex2: Result := RsHSV_Value; else Result := inherited GetAxisName(Index); end; end; function TJvHSVColorSpace.GetName: string; begin Result := RsHSV_FullName; end; function TJvHSVColorSpace.GetShortName: string; begin Result := RsHSV_ShortName; end; //=== { TJvYIQColorSpace } =================================================== function TJvYIQColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Y, I, Q: Integer; Red, Green, Blue: Integer; begin SplitColorParts(AColor, Red, Green, Blue); Y := Round(0.299*Red + 0.587*Green + 0.114*Blue); I := Round(0.596*Red - 0.275*Green - 0.321*Blue) + 128; Q := Round(0.212*Red - 0.523*Green + 0.311*Blue) + 128; Y := EnsureRange(Y, YIQ_MIN, YIQ_MAX); I := EnsureRange(I, YIQ_MIN, YIQ_MAX); Q := EnsureRange(Q, YIQ_MIN, YIQ_MAX); Result := inherited ConvertFromColor(JoinColorParts(Y, I, Q)); end; function TJvYIQColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Integer; Y, I, Q: Integer; begin SplitColorParts(AColor, Y, I, Q); //Y := Y; I := I - 128; Q := Q - 128; Red := Round(Y + 0.956*I + 0.620*Q); Green := Round(Y - 0.272*I - 0.647*Q); Blue := Round(Y - 1.108*I + 1.705*Q); Red := EnsureRange(Red , RGB_MIN, RGB_MAX); Green := EnsureRange(Green, RGB_MIN, RGB_MAX); Blue := EnsureRange(Blue, RGB_MIN, RGB_MAX); Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvYIQColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 128; end; function TJvYIQColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := YIQ_MAX; end; function TJvYIQColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := YIQ_MIN; end; function TJvYIQColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsYIQ_Y; axIndex1: Result := RsYIQ_I; axIndex2: Result := RsYIQ_Q; else Result := inherited GetAxisName(Index); end; end; function TJvYIQColorSpace.GetName: string; begin Result := RsYIQ_FullName; end; function TJvYIQColorSpace.GetShortName: string; begin Result := RsYIQ_ShortName; end; //=== { TJvYCCColorSpace } =================================================== function TJvYCCColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var Y, Cr, Cb: Integer; Red, Green, Blue: Integer; begin SplitColorParts(AColor, Red, Green, Blue); Y := Round( 0.299*Red + 0.587*Green + 0.114*Blue); Cr := Round(-0.150*Red - 0.293*Green + 0.443*Blue) + 128; Cb := Round( 0.438*Red - 0.367*Green - 0.071*Blue) + 128; Y := EnsureRange(Y, YCC_MIN, YCC_MAX); Cr := EnsureRange(Cr, YCC_MIN, YCC_MAX); Cb := EnsureRange(Cb, YCC_MIN, YCC_MAX); Result := inherited ConvertFromColor(JoinColorParts(Y, Cr, Cb)); end; function TJvYCCColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Integer; Y, Cr, Cb: Integer; begin SplitColorParts(AColor, Y, Cr, Cb); Y := Y; Cr := Cr - 128; Cb := Cb - 128; Red := Round(Y - 0.001*Cr + 1.600*Cb); Green := Round(Y - 0.388*Cr - 0.816*Cb); Blue := Round(Y + 2.000*Cr + 0.002*Cb); Red := EnsureRange(Red , RGB_MIN, RGB_MAX); Green := EnsureRange(Green, RGB_MIN, RGB_MAX); Blue := EnsureRange(Blue, RGB_MIN, RGB_MAX); Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvYCCColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 128; end; function TJvYCCColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := YCC_MAX; end; function TJvYCCColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := YCC_MIN; end; function TJvYCCColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsYCC_Y; axIndex1: Result := RsYCC_Cr; axIndex2: Result := RsYCC_Cb; else Result := inherited GetAxisName(Index); end; end; function TJvYCCColorSpace.GetName: string; begin Result := RsYCC_FullName; end; function TJvYCCColorSpace.GetShortName: string; begin Result := RsYCC_ShortName; end; //=== { TJvXYZColorSpace } =================================================== function TJvXYZColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var X, Y, Z: Integer; Red, Green, Blue: Integer; begin SplitColorParts(AColor, Red, Green, Blue); X := Round( 0.618*Red + 0.177*Green + 0.205*Blue); Y := Round( 0.299*Red + 0.587*Green + 0.114*Blue); Z := Round( 0.056*Green + 0.944*Blue); X := EnsureRange(X, XYZ_MIN, XYZ_MAX); Y := EnsureRange(Y, XYZ_MIN, XYZ_MAX); Z := EnsureRange(Z, XYZ_MIN, XYZ_MAX); Result := inherited ConvertFromColor(JoinColorParts(X, Y, Z)); end; function TJvXYZColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Integer; X, Y, Z: Integer; begin SplitColorParts(AColor, X, Y, Z); Red := Round( 1.876*X - 0.533*Y - 0.343*Z); Green := Round(-0.967*X + 1.998*Y - 0.031*Z); Blue := Round( 0.057*X - 0.118*Y + 1.061*Z); Red := EnsureRange(Red , RGB_MIN, RGB_MAX); Green := EnsureRange(Green, RGB_MIN, RGB_MAX); Blue := EnsureRange(Blue, RGB_MIN, RGB_MAX); Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvXYZColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 128; end; function TJvXYZColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := XYZ_MAX; end; function TJvXYZColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := XYZ_MIN; end; function TJvXYZColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsXYZ_X; axIndex1: Result := RsXYZ_Y; axIndex2: Result := RsXYZ_Z; else Result := inherited GetAxisName(Index); end; end; function TJvXYZColorSpace.GetName: string; begin Result := RsXYZ_FullName; end; function TJvXYZColorSpace.GetShortName: string; begin Result := RsXYZ_ShortName; end; //=== { TJvLABColorSpace } =================================================== function TJvLABColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var X, Y, Z: Extended; L, A, B: Integer; Red, Green, Blue: Integer; function Calc(Value: Extended): Extended; begin if Value > 0.008856 then Result := Power(Value, 1.0 / 3.0) else Result := 7.7787 * Value + (16.0 / 116.0); end; begin SplitColorParts(AColor, Red, Green, Blue); X := (0.618*Red + 0.177*Green + 0.205*Blue) / XYZ_MAX; Y := (0.299*Red + 0.587*Green + 0.114*Blue) / XYZ_MAX; Z := ( 0.056*Green + 0.944*Blue) / XYZ_MAX; X := EnsureRange(X, 0.0, 1.0); Y := EnsureRange(Y, 0.0, 1.0); Z := EnsureRange(Z, 0.0, 1.0); if Y > 0.008856 then L := Round(116.0 * Power(Y, 1.0 / 3.0) - 16.0) else L := Round(903.3 * Y); A := Round(500.0 *(Calc(X) - Calc(Y)))+128; B := Round(200.0 *(Calc(Y) - Calc(Z)))+128; L := EnsureRange(L, LAB_MIN, LAB_MAX); A := EnsureRange(A, LAB_MIN, LAB_MAX); B := EnsureRange(B, LAB_MIN, LAB_MAX); Result := inherited ConvertFromColor(JoinColorParts(L, A, B)); end; function TJvLABColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; var Red, Green, Blue: Integer; X, Y, Z: Extended; L, A, B: Integer; function Calc(Value: Extended): Extended; begin if Value > 0.207 then Result := Power(Value, 3.0) else Result := ((116.0 * Value) - 16.0) / 903.3; end; begin SplitColorParts(AColor, L, A, B); if L > 8 then Y := XYZ_MAX * Power((L + 16.0) / 116.0, 3.0) else Y := (XYZ_MAX * L) / 903.3; X := XYZ_MAX * Calc(((A-128) / 500.0) + ((L + 16.0) / 116.0)); Z := XYZ_MAX * Calc(((L + 16.0) / 116.0) - ((B-128) / 200.0)); X := EnsureRange(X, XYZ_MIN, XYZ_MAX); Y := EnsureRange(Y, XYZ_MIN, XYZ_MAX); Z := EnsureRange(Z, XYZ_MIN, XYZ_MAX); Red := Round( 1.876*X - 0.533*Y - 0.343*Z); Green := Round(-0.967*X + 1.998*Y - 0.031*Z); Blue := Round( 0.057*X - 0.118*Y + 1.061*Z); Red := EnsureRange(Red , RGB_MIN, RGB_MAX); Green := EnsureRange(Green, RGB_MIN, RGB_MAX); Blue := EnsureRange(Blue, RGB_MIN, RGB_MAX); Result := inherited ConvertToColor(JoinColorParts(Red, Green, Blue)); end; function TJvLABColorSpace.GetAxisDefault(Index: TJvAxisIndex): Byte; begin Result := 50; end; function TJvLABColorSpace.GetAxisMax(Index: TJvAxisIndex): Byte; begin Result := LAB_MAX; end; function TJvLABColorSpace.GetAxisMin(Index: TJvAxisIndex): Byte; begin Result := LAB_MIN; end; function TJvLABColorSpace.GetAxisName(Index: TJvAxisIndex): string; begin case Index of axIndex0: Result := RsLAB_L; axIndex1: Result := RsLAB_A; axIndex2: Result := RsLAB_B; else Result := inherited GetAxisName(Index); end; end; function TJvLABColorSpace.GetName: string; begin Result := RsLAB_FullName; end; function TJvLABColorSpace.GetShortName: string; begin Result := RsLAB_ShortName; end; //=== { TJvDEFColorSpace } =================================================== constructor TJvDEFColorSpace.Create(ColorID: TJvFullColorSpaceID); begin inherited Create(ColorID); FDelphiColors := TStringList.Create; // ignore duplicates FDelphiColors.Duplicates := dupIgnore; GetColorValues(GetColorValuesCallBack); AddDelphiColor(clNone); end; destructor TJvDEFColorSpace.Destroy; begin FDelphiColors.Free; inherited Destroy; end; procedure TJvDEFColorSpace.GetColorValuesCallBack(const S: string); var AColor: TColor; begin AColor := StringToColor(S); AddCustomColor(AColor,Copy(S,3,Length(S)-2),ColorToPrettyName(AColor)); end; procedure TJvDEFColorSpace.AddDelphiColor(Value: TColor); begin AddCustomColor(Value,ColorToString(Value),ColorToPrettyName(Value)); end; procedure TJvDEFColorSpace.AddCustomColor(AColor: TColor; ShortName, PrettyName: string); begin if FDelphiColors.IndexOfObject(TObject(AColor)) = -1 then begin FDelphiColors.Values[ShortName] := PrettyName; FDelphiColors.Objects[FDelphiColors.IndexOfName(ShortName)] := TObject(AColor); end; end; function TJvDEFColorSpace.ConvertFromColor(AColor: TColor): TJvFullColor; var I: Integer; NewColor: TColor; begin NewColor := clNone; for I := 0 to FDelphiColors.Count - 1 do if AColor = TColor(FDelphiColors.Objects[I]) then begin NewColor := AColor; Break; end; Result := inherited ConvertFromColor(NewColor); if NewColor = clNone then // mark it as clNone Result := Result or JvSpecialFullColorMask else if NewColor = clDefault then // mark it as clDefault Result := Result or JvSpecialFullColorMask else if (NewColor and JvSystemColorMask) = JvSystemColorMask then // mark it as predefined color Result := Result or JvSystemFullColorMask else if (NewColor and JvSystemColorMask) = 0 then Result := ColorSpaceManager.ColorSpace[csRGB].ConvertFromColor(NewColor) // should never happend because there should be no way ... else raise EJvColorSpaceError.CreateResFmt(@RsEInconvertibleColor, [Cardinal(NewColor)]); end; function TJvDEFColorSpace.ConvertToColor(AColor: TJvFullColor): TColor; begin Result := inherited ConvertToColor(AColor); case AColor and JvSubFullColorMask of JvSystemFullColorMask: Result := Cardinal(Result) or JvSystemColorMask; JvSpecialFullColorMask: begin if Result = (clNone and $FFFFFF) then Result := clNone else if Result = (clDefault and $FFFFFF) then Result := clDefault else raise EJvColorSpaceError.CreateResFmt(@RsEInconvertibleColor, [Cardinal(AColor)]); end; else raise EJvColorSpaceError.CreateResFmt(@RsEInconvertibleColor, [Cardinal(AColor)]); end; end; function TJvDEFColorSpace.GetColorName(Index: Integer): string; begin if (Index >= 0) and (Index < FDelphiColors.Count) then Result := FDelphiColors.Names[Index] else Result := ''; end; function TJvDEFColorSpace.GetPrettyName(Index: Integer): string; begin Result := FDelphiColors.Values[FDelphiColors.Names[Index]]; end; function TJvDEFColorSpace.GetColorValue(Index: Integer): TColor; begin if (Index >= 0) and (Index < FDelphiColors.Count) then Result := TColor(FDelphiColors.Objects[Index]) else Result := clNone; end; function TJvDEFColorSpace.GetName: string; begin Result := RsDEF_FullName; end; function TJvDEFColorSpace.GetShortName: string; begin Result := RsDEF_ShortName; end; function TJvDEFColorSpace.GetNumberOfColors: Cardinal; begin Result := FDelphiColors.Count; end; //=== { TJvColorSpaceManager } =============================================== constructor TJvColorSpaceManager.Create; begin inherited Create; FColorSpaceList := TList.Create; end; destructor TJvColorSpaceManager.Destroy; var Index: Integer; begin for Index := 0 to FColorSpaceList.Count - 1 do TJvColorSpace(FColorSpaceList.Items[Index]).Free; FColorSpaceList.Free; inherited Destroy; end; function TJvColorSpaceManager.ConvertToID(AColor: TJvFullColor; DestID: TJvFullColorSpaceID): TJvFullColor; var SourceID: TJvFullColorSpaceID; Color: TColor; begin SourceID := GetColorSpaceID(AColor); if SourceID = DestID then Result := AColor else begin Color := ColorToRGB(ColorSpace[SourceID].ConvertToColor(AColor)); Result := ColorSpace[DestID].ConvertFromColor(Color); end; end; function TJvColorSpaceManager.ConvertToColor(AColor: TJvFullColor): TColor; begin Result := ColorSpace[GetColorSpaceID(AColor)].ConvertToColor(AColor); end; function TJvColorSpaceManager.ConvertFromColor(AColor: TColor): TJvFullColor; var MaskedColor:Cardinal; begin MaskedColor := Cardinal(AColor) and JvSystemColorMask; if (AColor = clNone) or (AColor = clDefault) or (MaskedColor = JvSystemColorMask) then Result := ColorSpace[csDEF].ConvertFromColor(AColor) else if MaskedColor = 0 then Result := ColorSpace[csRGB].ConvertFromColor(AColor) else raise EJvColorSpaceError.CreateResFmt(@RsEInconvertibleColor, [Cardinal(AColor)]); end; function TJvColorSpaceManager.GetColorSpaceID(AColor: TJvFullColor): TJvFullColorSpaceID; var I: Integer; begin Result := TJvFullColorSpaceID(AColor shr 24) and csID_MASK; for I := 0 to Count - 1 do if ColorSpaceByIndex[I].ID = Result then Exit; raise EJvColorSpaceError.CreateResFmt(@RsEIllegalID, [Ord(Result)]); end; function TJvColorSpaceManager.GetColorSpace(ID: TJvFullColorSpaceID): TJvColorSpace; var I: Integer; begin Result := nil; for I := 0 to FColorSpaceList.Count - 1 do begin Result := TJvColorSpace(FColorSpaceList.Items[I]); if Result.ID = ID then Break; end; if Result = nil then raise EJvColorSpaceError.CreateResFmt(@RsECSNotFound, [Ord(ID)]); end; function TJvColorSpaceManager.GetCount: Integer; begin Result := FColorSpaceList.Count; end; function TJvColorSpaceManager.GetColorSpaceByIndex(Index: Integer): TJvColorSpace; begin Result := TJvColorSpace(FColorSpaceList.Items[Index]); end; procedure TJvColorSpaceManager.RegisterColorSpace(NewColorSpace: TJvColorSpace); var Index: Integer; CS: TJvColorSpace; begin for Index := 0 to FColorSpaceList.Count - 1 do begin CS := TJvColorSpace(FColorSpaceList.Items[Index]); if CS.ID = NewColorSpace.ID then raise EJvColorSpaceError.CreateResFmt(@RsECSAlreadyExists, [CS.ID, CS.Name]); end; FColorSpaceList.Add(Pointer(NewColorSpace)); end; procedure TJvColorSpaceManager.UnRegisterColorSpace(AColorSpace: TJvColorSpace); begin // maybe more than one instance of one class while FColorSpaceList.Remove(AColorSpace) >= 0 do ; end; initialization {$IFDEF UNITVERSIONING} RegisterUnitVersion(HInstance, UnitVersioning); {$ENDIF UNITVERSIONING} finalization FreeAndNil(GlobalColorSpaceManager); {$IFDEF UNITVERSIONING} UnregisterUnitVersion(HInstance); {$ENDIF UNITVERSIONING} end.