git-svn-id: https://192.168.0.254/svn/Componentes.Terceros.jvcl@19 7f62d464-2af8-f54e-996c-e91b33f51cbe
405 lines
13 KiB
ObjectPascal
405 lines
13 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
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: ColorRotate.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.delphi-jedi.org
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
// $Id: JvFullColorRotate.pas 12461 2009-08-14 17:21:33Z obones $
|
|
|
|
unit JvFullColorRotate;
|
|
|
|
{$I jvcl.inc}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$IFDEF UNITVERSIONING}
|
|
JclUnitVersioning,
|
|
{$ENDIF UNITVERSIONING}
|
|
Windows, Classes, Graphics,
|
|
JvFullColorSpaces;
|
|
|
|
type
|
|
TJvRotateColor = (rcCommon, rcRed, rcGreen, rcBlue);
|
|
|
|
TJvSaturationMethod = (smRange, smLoop);
|
|
|
|
TJvRotateValueType = -255..255;
|
|
|
|
TJvRotateValue = class(TPersistent)
|
|
private
|
|
FValue: TJvRotateValueType;
|
|
FSaturationMethod: TJvSaturationMethod;
|
|
public
|
|
constructor Create; reintroduce;
|
|
property Value: TJvRotateValueType read FValue write FValue default 0;
|
|
property SaturationMethod: TJvSaturationMethod read FSaturationMethod write FSaturationMethod default smRange;
|
|
|
|
procedure Assign(Value: TJvRotateValue); reintroduce;
|
|
end;
|
|
|
|
TJvAxisDelta = class(TPersistent)
|
|
private
|
|
FConstituents: array [TJvAxisIndex] of TJvRotateValue;
|
|
function GetConstituents(Index: TJvAxisIndex): TJvRotateValue;
|
|
procedure SetConstituents(Index: TJvAxisIndex; const Value: TJvRotateValue);
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Assign(Value: TJvAxisDelta); reintroduce;
|
|
property Constituents[Index: TJvAxisIndex]: TJvRotateValue read GetConstituents write SetConstituents; default;
|
|
end;
|
|
|
|
TJvColorDelta = class(TPersistent)
|
|
private
|
|
FColorID: TJvFullColorSpaceID;
|
|
FAxisRed: TJvAxisDelta;
|
|
FAxisGreen: TJvAxisDelta;
|
|
FAxisBlue: TJvAxisDelta;
|
|
procedure SetAxisBlue(const Value: TJvAxisDelta);
|
|
procedure SetAxisGreen(const Value: TJvAxisDelta);
|
|
procedure SetAxisRed(const Value: TJvAxisDelta);
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Assign(Value: TJvColorDelta); reintroduce;
|
|
property ColorID: TJvFullColorSpaceID read FColorID write FColorID default csRGB;
|
|
property AxisRed: TJvAxisDelta read FAxisRed write SetAxisRed;
|
|
property AxisGreen: TJvAxisDelta read FAxisGreen write SetAxisGreen;
|
|
property AxisBlue: TJvAxisDelta read FAxisBlue write SetAxisBlue;
|
|
end;
|
|
|
|
function RotateColor(AColor: TJvFullColor; AColorDelta: TJvColorDelta): TJvFullColor;
|
|
procedure RotateBitmap(SourceBitmap, DestBitmap: TBitmap; AColorDelta: TJvColorDelta);
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
const
|
|
UnitVersioning: TUnitVersionInfo = (
|
|
RCSfile: '$URL: https://jvcl.svn.sourceforge.net/svnroot/jvcl/tags/JVCL3_39/run/JvFullColorRotate.pas $';
|
|
Revision: '$Revision: 12461 $';
|
|
Date: '$Date: 2009-08-14 19:21:33 +0200 (ven., 14 août 2009) $';
|
|
LogPath: 'JVCL\run'
|
|
);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
implementation
|
|
|
|
uses
|
|
JvTypes;
|
|
|
|
function RotateColor(AColor: TJvFullColor; AColorDelta: TJvColorDelta): TJvFullColor;
|
|
var
|
|
I: TJvAxisIndex;
|
|
MinAxis: array [TJvAxisIndex] of Byte;
|
|
MaxAxis: array [TJvAxisIndex] of Byte;
|
|
ValueAxis: array [TJvAxisIndex] of SmallInt;
|
|
ColorRed, ColorGreen, ColorBlue: TColor;
|
|
MaxColorAxis:Integer;
|
|
SourceColorSpace, DeltaColorSpace: TJvColorSpace;
|
|
LColor: TColor;
|
|
|
|
function DoRotate(AValue: TJvFullColor; AAxisDelta: TJvAxisDelta): TColor;
|
|
var
|
|
I: TJvAxisIndex;
|
|
Range: Integer;
|
|
begin
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
ValueAxis[I] := Integer(GetAxisValue(AValue, I)) + AAxisDelta[I].Value;
|
|
if AAxisDelta[I].SaturationMethod = smRange then
|
|
begin
|
|
if ValueAxis[I] > MaxAxis[I] then
|
|
ValueAxis[I] := MaxAxis[I];
|
|
if ValueAxis[I] < MinAxis[I] then
|
|
ValueAxis[I] := MinAxis[I];
|
|
end
|
|
else
|
|
begin
|
|
Range := MaxAxis[I] - MinAxis[I] + 1;
|
|
while ValueAxis[I] < MinAxis[I] do
|
|
Inc(ValueAxis[I], Range);
|
|
while ValueAxis[I] > MaxAxis[I] do
|
|
Dec(ValueAxis[I], Range);
|
|
end;
|
|
end;
|
|
Result :=
|
|
(ValueAxis[axIndex0]) or (ValueAxis[axIndex1] shl 8) or (ValueAxis[axIndex2] shl 16);
|
|
end;
|
|
|
|
begin
|
|
with ColorSpaceManager do
|
|
begin
|
|
SourceColorSpace := ColorSpace[GetColorSpaceID(AColor)];
|
|
LColor := SourceColorSpace.ConvertToColor(AColor);
|
|
DeltaColorSpace := ColorSpace[AColorDelta.ColorID];
|
|
|
|
with DeltaColorSpace do
|
|
begin
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
MinAxis[I] := AxisMin[I];
|
|
MaxAxis[I] := AxisMax[I];
|
|
end;
|
|
ColorRed := ConvertToColor(DoRotate(ConvertFromColor(LColor and $000000FF), AColorDelta.AxisRed));
|
|
ColorGreen := ConvertToColor(DoRotate(ConvertFromColor(LColor and $0000FF00), AColorDelta.AxisGreen));
|
|
ColorBlue := ConvertToColor(DoRotate(ConvertFromColor(LColor and $00FF0000), AColorDelta.AxisBlue));
|
|
|
|
MaxColorAxis := 255;
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
ValueAxis[I] := (ColorRed and $FF) + (ColorGreen and $FF) + (ColorBlue and $FF);
|
|
if ValueAxis[I] > MaxColorAxis then
|
|
MaxColorAxis := ValueAxis[I];
|
|
ColorRed := ColorRed shr 8;
|
|
ColorGreen := ColorGreen shr 8;
|
|
ColorBlue := ColorBlue shr 8;
|
|
end;
|
|
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
ValueAxis[I] := ValueAxis[I] + 255 - MaxColorAxis;
|
|
if ValueAxis[I] < 0 then
|
|
ValueAxis[I] := 0;
|
|
end;
|
|
LColor := ValueAxis[axIndex0] or (ValueAxis[axIndex1] shl 8) or (ValueAxis[axIndex2] shl 16);
|
|
end;
|
|
Result := SourceColorSpace.ConvertFromColor(LColor);
|
|
end;
|
|
end;
|
|
|
|
procedure RotateBitmap(SourceBitmap, DestBitmap: TBitmap; AColorDelta: TJvColorDelta);
|
|
type
|
|
TFullColorValue = array [TJvAxisIndex] of SmallInt;
|
|
PFullColorValue = ^TFullColorValue;
|
|
var
|
|
OriginalPixelFormat: TPixelFormat;
|
|
Colors: array [TJvAxisIndex,Byte] of TFullColorValue;
|
|
ColorR, ColorB, ColorG, ColorFusion: TFullColorValue;
|
|
I: TJvAxisIndex;
|
|
J: Byte;
|
|
X, Y: Integer;
|
|
MinAxis: array [TJvAxisIndex] of SmallInt;
|
|
MaxAxis: array [TJvAxisIndex] of SmallInt;
|
|
MaxColorAxis: SmallInt;
|
|
DeltaColorSpace: TJvColorSpace;
|
|
DestLine, SourceLine: PCardinal;
|
|
|
|
procedure DoRotate(Color: TColor; AAxisDelta: TJvAxisDelta; out DestColor: TFullColorValue);
|
|
var
|
|
I: TJvAxisIndex;
|
|
Range: Integer;
|
|
FullColor: TJvFullColor;
|
|
ColorValue: TFullColorValue;
|
|
begin
|
|
FullColor := DeltaColorSpace.ConvertFromColor(Color);
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
ColorValue[I] := Integer(GetAxisValue(FullColor, I)) + AAxisDelta[I].Value;
|
|
if AAxisDelta[I].SaturationMethod = smRange then
|
|
begin
|
|
if ColorValue[I] > MaxAxis[I] then
|
|
ColorValue[I] := MaxAxis[I];
|
|
if ColorValue[I] < MinAxis[I] then
|
|
ColorValue[I] := MinAxis[I];
|
|
end
|
|
else
|
|
begin
|
|
Range := MaxAxis[I] - MinAxis[I] + 1;
|
|
while ColorValue[I] < MinAxis[I] do
|
|
Inc(ColorValue[I], Range);
|
|
while ColorValue[I] > MaxAxis[I] do
|
|
Dec(ColorValue[I], Range);
|
|
end;
|
|
end;
|
|
Color := DeltaColorSpace.ConvertToColor(ColorValue[axIndex0] or
|
|
(ColorValue[axIndex1] shl 8) or (ColorValue[axIndex2] shl 16));
|
|
DestColor[axIndex0] := Color and $FF;
|
|
DestColor[axIndex1] := (Color shr 8) and $FF;
|
|
DestColor[axIndex2] := (Color shr 16) and $FF;
|
|
end;
|
|
|
|
begin
|
|
DestBitmap.Width := SourceBitmap.Width;
|
|
DestBitmap.Height := SourceBitmap.Height;
|
|
OriginalPixelFormat := SourceBitmap.PixelFormat;
|
|
SourceBitmap.PixelFormat := pf32bit;
|
|
DestBitmap.PixelFormat := pf32bit;
|
|
with ColorSpaceManager do
|
|
begin
|
|
DeltaColorSpace := ColorSpace[AColorDelta.ColorID];
|
|
with DeltaColorSpace do
|
|
begin
|
|
for I := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
begin
|
|
MinAxis[I] := AxisMin[I];
|
|
MaxAxis[I] := AxisMax[I];
|
|
end;
|
|
for J := Low(Byte) to High(Byte) do
|
|
begin
|
|
DoRotate(TColor(J),AColorDelta.AxisRed,Colors[axIndex0,J]);
|
|
DoRotate(TColor(J shl 8),AColorDelta.AxisGreen,Colors[axIndex1,J]);
|
|
DoRotate(TColor(J shl 16),AColorDelta.AxisBlue,Colors[axIndex2,J]);
|
|
end;
|
|
|
|
for Y := 0 to DestBitmap.Height-1 do
|
|
begin
|
|
SourceLine := SourceBitmap.ScanLine[Y];
|
|
DestLine := DestBitmap.ScanLine[Y];
|
|
for X := 0 to DestBitmap.Width-1 do
|
|
begin
|
|
ColorR := Colors[axIndex0,(SourceLine^ shr 16) and $FF]; //
|
|
ColorG := Colors[axIndex1,(SourceLine^ shr 8) and $FF]; // Bitmap Color Format is
|
|
ColorB := Colors[axIndex2,(SourceLine^) and $FF]; // (MSB)0RGB(LSB)
|
|
ColorFusion[axIndex0] := ColorR[axIndex0] + ColorG[axIndex0] + ColorB[axIndex0];
|
|
ColorFusion[axIndex1] := ColorR[axIndex1] + ColorG[axIndex1] + ColorB[axIndex1];
|
|
ColorFusion[axIndex2] := ColorR[axIndex2] + ColorG[axIndex2] + ColorB[axIndex2];
|
|
MaxColorAxis := 255;
|
|
if ColorFusion[axIndex0] > MaxColorAxis then
|
|
MaxColorAxis := ColorFusion[axIndex0];
|
|
if ColorFusion[axIndex1] > MaxColorAxis then
|
|
MaxColorAxis := ColorFusion[axIndex1];
|
|
if ColorFusion[axIndex2] > MaxColorAxis then
|
|
MaxColorAxis := ColorFusion[axIndex2];
|
|
ColorFusion[axIndex0] := ColorFusion[axIndex0] + 255 - MaxColorAxis;
|
|
if ColorFusion[axIndex0] < 0 then
|
|
ColorFusion[axIndex0] := 0;
|
|
ColorFusion[axIndex1] := ColorFusion[axIndex1] + 255 - MaxColorAxis;
|
|
if ColorFusion[axIndex1] < 0 then
|
|
ColorFusion[axIndex1] := 0;
|
|
ColorFusion[axIndex2] := ColorFusion[axIndex2] + 255 - MaxColorAxis;
|
|
if ColorFusion[axIndex2] < 0 then
|
|
ColorFusion[axIndex2] := 0;
|
|
DestLine^ := // Bitmap Color Format is (MSB)0RGB(LSB)
|
|
(ColorFusion[axIndex0] shl 16) or (ColorFusion[axIndex1] shl 8) or (ColorFusion[axIndex2]);
|
|
Inc(SourceLine);
|
|
Inc(DestLine);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
SourceBitmap.PixelFormat := OriginalPixelFormat;
|
|
DestBitmap.PixelFormat := OriginalPixelFormat;
|
|
end;
|
|
|
|
//=== { TJvAxisDelta } =======================================================
|
|
|
|
constructor TJvAxisDelta.Create;
|
|
var
|
|
Index: TJvAxisIndex;
|
|
begin
|
|
inherited Create;
|
|
for Index := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
FConstituents[Index] := TJvRotateValue.Create;
|
|
end;
|
|
|
|
destructor TJvAxisDelta.Destroy;
|
|
var
|
|
Index: TJvAxisIndex;
|
|
begin
|
|
for Index := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
FConstituents[Index].Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvAxisDelta.Assign(Value: TJvAxisDelta);
|
|
var
|
|
Index: TJvAxisIndex;
|
|
begin
|
|
for Index := Low(TJvAxisIndex) to High(TJvAxisIndex) do
|
|
FConstituents[Index].Assign(Value[Index]);
|
|
end;
|
|
|
|
function TJvAxisDelta.GetConstituents(Index: TJvAxisIndex): TJvRotateValue;
|
|
begin
|
|
Result := FConstituents[Index];
|
|
end;
|
|
|
|
procedure TJvAxisDelta.SetConstituents(Index: TJvAxisIndex;
|
|
const Value: TJvRotateValue);
|
|
begin
|
|
FConstituents[Index].Assign(Value);
|
|
end;
|
|
|
|
//=== { TJvColorDelta } ======================================================
|
|
|
|
constructor TJvColorDelta.Create;
|
|
begin
|
|
inherited Create;
|
|
FColorID := csRGB;
|
|
FAxisRed := TJvAxisDelta.Create;
|
|
FAxisGreen := TJvAxisDelta.Create;
|
|
FAxisBlue := TJvAxisDelta.Create;
|
|
end;
|
|
|
|
destructor TJvColorDelta.Destroy;
|
|
begin
|
|
FAxisRed.Free;
|
|
FAxisGreen.Free;
|
|
FAxisBlue.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
procedure TJvColorDelta.Assign(Value: TJvColorDelta);
|
|
begin
|
|
AxisRed.Assign(Value.AxisRed);
|
|
AxisGreen.Assign(Value.AxisGreen);
|
|
AxisBlue.Assign(Value.AxisBlue);
|
|
ColorID := Value.ColorID;
|
|
end;
|
|
|
|
procedure TJvColorDelta.SetAxisBlue(const Value: TJvAxisDelta);
|
|
begin
|
|
FAxisBlue.Assign(Value);
|
|
end;
|
|
|
|
procedure TJvColorDelta.SetAxisGreen(const Value: TJvAxisDelta);
|
|
begin
|
|
FAxisGreen.Assign(Value);
|
|
end;
|
|
|
|
procedure TJvColorDelta.SetAxisRed(const Value: TJvAxisDelta);
|
|
begin
|
|
FAxisRed.Assign(Value);
|
|
end;
|
|
|
|
//=== { TJvRotateValue } =====================================================
|
|
|
|
constructor TJvRotateValue.Create;
|
|
begin
|
|
FValue := 0;
|
|
FSaturationMethod := smLoop;
|
|
end;
|
|
|
|
procedure TJvRotateValue.Assign(Value: TJvRotateValue);
|
|
begin
|
|
FValue := Value.Value;
|
|
FSaturationMethod := Value.SaturationMethod;
|
|
end;
|
|
|
|
{$IFDEF UNITVERSIONING}
|
|
initialization
|
|
RegisterUnitVersion(HInstance, UnitVersioning);
|
|
|
|
finalization
|
|
UnregisterUnitVersion(HInstance);
|
|
{$ENDIF UNITVERSIONING}
|
|
|
|
end.
|