diff --git a/bcpanel.pas b/bcpanel.pas index 46cd7ea..9471628 100644 --- a/bcpanel.pas +++ b/bcpanel.pas @@ -122,6 +122,7 @@ TBCPanel = class(TCustomBCPanel) property Border; property BorderBCStyle; property Caption; + property Color; property Constraints; property DockSite; property DragCursor; diff --git a/bgracontrols.lpk b/bgracontrols.lpk index 76183b1..d056b07 100644 --- a/bgracontrols.lpk +++ b/bgracontrols.lpk @@ -361,7 +361,7 @@ - + diff --git a/bgraimagemanipulation.pas b/bgraimagemanipulation.pas index 1af95f4..7621347 100644 --- a/bgraimagemanipulation.pas +++ b/bgraimagemanipulation.pas @@ -65,6 +65,16 @@ - removed the use of DeltaX, DeltaY in render/mouse/etc - CropAreas Area and ScaledArea property is updated during the mouse events - rewriting of the methods for taking cropped images + -08 - the CropArea.Area property can be specified in Pixels,Cm,Inch + - Alt on MouseUp Undo the Crop Area Changes,Optimized mouse events + -09 - OverAnchor gives precedence to the selected area than Z Order + - EmptyImage property; CropAreas when Image is Empty; Old Code deleted and optimized + - XML Use Laz2_XMLCfg in fpc + - divide by zero in getImageRect on Component Loading + - EmptyImage size to ClientRect when Width/Height=0; Mouse Events when Image is Empty + - CropArea Rotate and Flip + - CropArea Duplicate and SetSize + - NewCropAreaDefault property (to Cm); ResolutionUnitConvert function; SetEmptyImageSizeToCropAreas ============================================================================ } @@ -77,13 +87,19 @@ interface +{$IFDEF FPC} + {$DEFINE USE_Laz2_XMLCfg} +{$ENDIF} + uses - Classes, Contnrs, SysUtils, {$IFDEF FPC}LCLIntf, LResources,{$ENDIF} + Classes, Contnrs, SysUtils, + {$IFDEF FPC}LCLIntf, LResources, FPImage, {$ENDIF} Forms, Controls, Graphics, Dialogs, - {$IFNDEF FPC}Windows, Messages, BGRAGraphics, GraphType, FPImage, {$ENDIF} - XMLConf, BCBaseCtrls, BGRABitmap, BGRABitmapTypes, BGRAGradientScanner; + {$IFNDEF FPC}Windows, Messages, BGRAGraphics, GraphType,{$ENDIF} + {$IFDEF USE_Laz2_XMLCfg}Laz2_XMLCfg,{$ELSE}XMLConf,{$ENDIF} + BCBaseCtrls, BGRABitmap, BGRABitmapTypes, BGRAGradientScanner; - {$IFNDEF FPC} +{$IFNDEF FPC} const crSizeNW = TCursor(-23); crSizeN = TCursor(-24); @@ -100,7 +116,7 @@ interface crHSplit = TCursor(-14); crVSplit = TCursor(-15); crMultiDrag = TCursor(-16); - {$ENDIF} +{$ENDIF} type TCoord = packed record @@ -126,15 +142,19 @@ interface end; TBGRAImageManipulation = class; + TCropAreaList = class; { TCropArea } BoolParent = (bFalse=0, bTrue=1, bParent=2); + TCropAreaIcons = set of (cIcoIndex, cIcoLockSize, cIcoLockMove); TCropArea = class(TObject) protected fOwner :TBGRAImageManipulation; - rScaledArea, - rArea :TRect; + OwnerList:TCropAreaList; + rScaledArea:TRect; + rArea :TRectF; + rAreaUnit:TResolutionUnit; rRatio :TRatio; rAspectX, rAspectY, @@ -143,55 +163,88 @@ TCropArea = class(TObject) rAspectRatio, rName: String; rKeepAspectRatio: BoolParent; + Loading :Boolean; + rIcons: TCropAreaIcons; procedure CopyAspectFromParent; procedure setAspectRatio(AValue: string); procedure setKeepAspectRatio(AValue: BoolParent); procedure setScaledArea(AValue: TRect); - function getLeft: Longint; - procedure setLeft(AValue: Longint); - function getTop: Longint; - procedure setTop(AValue: Longint); - function getWidth: Longint; - procedure setWidth(AValue: Longint); - function getHeight: Longint; - procedure setHeight(AValue: Longint); + function getLeft: Single; + procedure setLeft(AValue: Single); + function getTop: Single; + procedure setTop(AValue: Single); + function getWidth: Single; + procedure setWidth(AValue: Single); + function getHeight: Single; + procedure setHeight(AValue: Single); + function getMaxHeight: Single; + function getMaxWidth: Single; function getRealAspectRatio(var ARatio: TRatio):Boolean; //return Real KeepAspect function getRealKeepAspectRatio:Boolean; function getIndex: Longint; function getIsNullSize: Boolean; - procedure setArea(AValue: TRect); + procedure setArea(AValue: TRectF); + procedure setAreaUnit(AValue: TResolutionUnit); procedure setName(AValue: String); + procedure setIcons(AValue: TCropAreaIcons); procedure Render_Refresh; + + procedure GetImageResolution(var resX, resY:Single; var resUnit:TResolutionUnit); procedure CalculateScaledAreaFromArea; procedure CalculateAreaFromScaledArea; + function GetPixelArea(const AValue: TRectF):TRect; - property ScaledArea :TRect read rScaledArea write setScaledArea; + function CheckScaledOutOfBounds(var AArea:TRect):Boolean; + function CheckAreaOutOfBounds(var AArea:TRectF):Boolean; + property ScaledArea :TRect read rScaledArea write setScaledArea; public - Rotate :double; + Rotate :Single; UserData :Integer; BorderColor :TBGRAPixel; - function getResampledBitmap(OriginalRect: TRect): TBGRABitmap; + function getResampledBitmap: TBGRABitmap; function getBitmap: TBGRABitmap; - constructor Create(AOwner: TBGRAImageManipulation; AArea: TRect; - ARotate: double = 0; - AUserData: Integer = 0); + constructor Create(AOwner: TBGRAImageManipulation; AArea: TRectF; + AAreaUnit: TResolutionUnit = ruNone; //Pixels + AUserData: Integer = -1); overload; + constructor Create(AOwner: TBGRAImageManipulation; + DuplicateFrom: TCropArea; InsertInList:Boolean); overload; destructor Destroy; override; - property Area :TRect read rArea write setArea; - property Top:Longint read getTop write setTop; - property Left:Longint read getLeft write setLeft; - property Width:Longint read getWidth write setWidth; - property Height:Longint read getHeight write setHeight; + //ZOrder + procedure BringToFront; + procedure BringToBack; + procedure BringForward; + procedure BringBackward; + + //Rotate/Flip + procedure RotateLeft; + procedure RotateRight; + procedure FlipHLeft; + procedure FlipHRight; + procedure FlipVUp; + procedure FlipVDown; + + procedure SetSize(AWidth, AHeight:Single); + + property Area:TRectF read rArea write setArea; + property AreaUnit:TResolutionUnit read rAreaUnit write setAreaUnit; + property Top:Single read getTop write setTop; + property Left:Single read getLeft write setLeft; + property Width:Single read getWidth write setWidth; + property Height:Single read getHeight write setHeight; + property MaxWidth:Single read getMaxWidth; + property MaxHeight:Single read getMaxHeight; property AspectRatio: string read rAspectRatio write setAspectRatio; property KeepAspectRatio: BoolParent read rKeepAspectRatio write setKeepAspectRatio default bParent; property Index:Longint read getIndex; property Name:String read rName write setName; property isNullSize: Boolean read getIsNullSize; + property Icons:TCropAreaIcons read rIcons write setIcons; end; { TCropAreaList } @@ -200,37 +253,102 @@ TCropAreaList = class(TObjectList) protected fOwner :TBGRAImageManipulation; rName :String; - loading :Boolean; + rLoading :Boolean; function getCropArea(aIndex: Integer): TCropArea; procedure setCropArea(aIndex: Integer; const Value: TCropArea); + procedure setLoading(AValue: Boolean); procedure Notify(Ptr: Pointer; Action: TListNotification); override; + property Loading :Boolean read rLoading write setLoading; public constructor Create(AOwner: TBGRAImageManipulation); + function add(aCropArea: TCropArea): integer; + + procedure Load(const XMLConf: TXMLConfig; XMLPath: String=''); + procedure Save(const XMLConf: TXMLConfig; XMLPath: String=''); + procedure LoadFromStream(Stream: TStream; XMLPath: String=''); + procedure LoadFromFile(const FileName: String; XMLPath: String=''); + procedure SaveToStream(Stream: TStream; XMLPath: String=''); + procedure SaveToFile(const FileName: String; XMLPath: String=''); + + //Rotate/Flip + procedure RotateLeft; + procedure RotateRight; + procedure FlipHLeft; + procedure FlipHRight; + procedure FlipVUp; + procedure FlipVDown; + property items[aIndex: integer] : TCropArea read getCropArea write setCropArea; default; property Name:String read rName write rName; - function add(aCropArea: TCropArea): integer; + end; + + TgetAllBitmapsCallback = procedure (Bitmap :TBGRABitmap; CropArea: TCropArea; AUserData:Integer) of object; + + { TBGRAEmptyImage } - procedure Load(const XMLConf: TXMLConfig); - procedure Save(const XMLConf: TXMLConfig); - procedure LoadFromStream(Stream: TStream); - procedure LoadFromFile(const FileName: string); - procedure SaveToStream(Stream: TStream); - procedure SaveToFile(const FileName: string); + TBGRAEmptyImage = class(TPersistent) + private + fOwner: TBGRAImageManipulation; + rAllow: Boolean; + rResolutionHeight: Single; + rResolutionUnit: TResolutionUnit; + rResolutionWidth: Single; + rShowBorder: Boolean; + + function getHeight: Integer; + function getWidth: Integer; + procedure SetResolutionUnit(AValue: TResolutionUnit); + + public + property Width:Integer read getWidth; + property Height:Integer read getHeight; + + constructor Create(AOwner: TBGRAImageManipulation); + + published + property Allow: Boolean read rAllow write rAllow default False; + property ResolutionUnit: TResolutionUnit read rResolutionUnit write SetResolutionUnit default ruPixelsPerCentimeter; + property ResolutionWidth: Single read rResolutionWidth write rResolutionWidth; + property ResolutionHeight: Single read rResolutionHeight write rResolutionHeight; + property ShowBorder: Boolean read rShowBorder write rShowBorder default False; end; - TgetAllBitmapsCallback = procedure (Bitmap :TBGRABitmap; CropArea: TCropArea) of object; + { TBGRANewCropAreaDefault } + + TBGRANewCropAreaDefault = class(TPersistent) + private + fOwner: TBGRAImageManipulation; + rAspectRatio: string; + rKeepAspectRatio: BoolParent; + rResolutionUnit: TResolutionUnit; + + public + constructor Create(AOwner: TBGRAImageManipulation); + + published + property ResolutionUnit: TResolutionUnit read rResolutionUnit write rResolutionUnit default ruPixelsPerCentimeter; + property AspectRatio: string read rAspectRatio write rAspectRatio; + property KeepAspectRatio: BoolParent read rKeepAspectRatio write rKeepAspectRatio default bFalse; + end; { TBGRAImageManipulation } - TCropAreaEvent = procedure (AOwner: TBGRAImageManipulation; CropArea: TCropArea) of object; + TCropAreaEvent = procedure (Sender: TBGRAImageManipulation; CropArea: TCropArea) of object; + TCropAreaLoadEvent = function (Sender: TBGRAImageManipulation; CropArea: TCropArea; + const XMLConf: TXMLConfig; const Path:String):Integer of object; + TCropAreaSaveEvent = procedure (Sender: TBGRAImageManipulation; CropArea: TCropArea; + const XMLConf: TXMLConfig; const Path:String) of object; + + TBGRAIMContextPopupEvent = procedure(Sender: TBGRAImageManipulation; CropArea: TCropArea; + AnchorSelected :TDirection; MousePos: TPoint; var Handled: Boolean) of object; + TBGRAImageManipulation = class(TBGRAGraphicCtrl) private { Private declarations } - fAnchorSize: byte; fAnchorSelected: TDirection; fBorderSize: byte; @@ -241,20 +359,23 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) fMinHeight: integer; fMinWidth: integer; fMouseCaught: boolean; - fStartPoint: TPoint; + fStartPoint, fEndPoint: TPoint; - + fStartArea: TRect; fRatio: TRatio; fSizeLimits: TSizeLimits; - fImageBitmap, fResampledBitmap, fBackground, fVirtualScreen: TBGRABitmap; + rNewCropAreaDefault: TBGRANewCropAreaDefault; + rOnContextPopup: TBGRAIMContextPopupEvent; function getAnchorSize: byte; + function getPixelsPerInch: Integer; procedure setAnchorSize(const Value: byte); function getEmpty: boolean; procedure setBitmap(const Value: TBGRABitmap); procedure setBorderSize(const Value: byte); procedure setAspectRatio(const Value: string); + procedure setEmptyImage(AValue: TBGRAEmptyImage); procedure setKeepAspectRatio(const Value: boolean); procedure setMinHeight(const Value: integer); procedure setMinWidth(const Value: integer); @@ -268,6 +389,10 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) rOnCropAreaDeleted: TCropAreaEvent; rOnCropAreaChanged: TCropAreaEvent; rOnSelectedCropAreaChanged: TCropAreaEvent; + rOnCropAreaLoad: TCropAreaLoadEvent; + rOnCropAreaSave: TCropAreaSaveEvent; + rEmptyImage: TBGRAEmptyImage; + rLoading: Boolean; function ApplyDimRestriction(Coords: TCoord; Direction: TDirection; Bounds: TRect; AKeepAspectRatio:Boolean): TCoord; function ApplyRatioToAxes(Coords: TCoord; Direction: TDirection; Bounds: TRect; ACropArea :TCropArea = Nil): TCoord; @@ -278,7 +403,10 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) function getImageRect(Picture: TBGRABitmap): TRect; function getWorkRect: TRect; function isOverAnchor(APoint :TPoint; var AnchorSelected :TDirection; var ACursor :TCursor) :TCropArea; + procedure CreateEmptyImage; + procedure CreateResampledBitmap; + procedure Loaded; override; procedure Paint; override; procedure RepaintBackground; procedure Resize; override; @@ -287,6 +415,7 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override; procedure MouseMove(Shift: TShiftState; X, Y: integer); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: integer); override; + procedure DoContextPopup(MousePos: TPoint; var Handled: Boolean); override; public { Public declarations } @@ -303,15 +432,21 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) procedure tests; //Crop Areas Manipulation functions - function addCropArea(AArea : TRect; ARotate :double = 0; AUserData: Integer = 0) :TCropArea; - function addScaledCropArea(AArea : TRect; ARotate :double = 0; AUserData: Integer = 0) :TCropArea; + function addCropArea(AArea : TRectF; AAreaUnit: TResolutionUnit = ruNone; + AUserData: Integer = -1) :TCropArea; + function addScaledCropArea(AArea : TRect; AUserData: Integer = -1) :TCropArea; procedure delCropArea(ACropArea :TCropArea); procedure clearCropAreas; - procedure getAllResampledBitmaps(ACallBack :TgetAllBitmapsCallback); - procedure getAllBitmaps(ACallBack :TgetAllBitmapsCallback); + procedure getAllResampledBitmaps(ACallBack :TgetAllBitmapsCallback; AUserData:Integer=0); + procedure getAllBitmaps(ACallBack :TgetAllBitmapsCallback; AUserData:Integer=0); + + procedure SetEmptyImageSizeToCropAreas(ReduceLarger: Boolean=False); + procedure SetEmptyImageSizeToNull; + procedure SetEmptyImageSize(AResolutionUnit: TResolutionUnit; AResolutionWidth, AResolutionHeight: Single); property SelectedCropArea :TCropArea read rSelectedCropArea write setSelectedCropArea; property CropAreas :TCropAreaList read rCropAreas; + property PixelsPerInch: Integer read getPixelsPerInch; published { Published declarations } @@ -322,21 +457,35 @@ TBGRAImageManipulation = class(TBGRAGraphicCtrl) property Bitmap: TBGRABitmap Read fImageBitmap Write setBitmap; property BorderSize: byte Read fBorderSize Write setBorderSize default 2; property AspectRatio: string Read fAspectRatio Write setAspectRatio; - property KeepAspectRatio: boolean Read fKeepAspectRatio - Write setKeepAspectRatio default True; + property KeepAspectRatio: boolean Read fKeepAspectRatio Write setKeepAspectRatio default True; property MinHeight: integer Read fMinHeight Write setMinHeight; property MinWidth: integer Read fMinWidth Write setMinWidth; property Empty: boolean Read getEmpty; + property EmptyImage: TBGRAEmptyImage read rEmptyImage write setEmptyImage stored True; + property NewCropAreaDefault: TBGRANewCropAreaDefault read rNewCropAreaDefault write rNewCropAreaDefault stored True; //Events property OnCropAreaAdded:TCropAreaEvent read rOnCropAreaAdded write rOnCropAreaAdded; property OnCropAreaDeleted:TCropAreaEvent read rOnCropAreaDeleted write rOnCropAreaDeleted; property OnCropAreaChanged:TCropAreaEvent read rOnCropAreaChanged write rOnCropAreaChanged; + property OnCropAreaLoad:TCropAreaLoadEvent read rOnCropAreaLoad write rOnCropAreaLoad; + property OnCropAreaSave:TCropAreaSaveEvent read rOnCropAreaSave write rOnCropAreaSave; //CropArea Parameter is the Old Selected Area, use SelectedCropArea property for current property OnSelectedCropAreaChanged:TCropAreaEvent read rOnSelectedCropAreaChanged write rOnSelectedCropAreaChanged; + + property OnContextPopup: TBGRAIMContextPopupEvent read rOnContextPopup write rOnContextPopup; +(* property OnStartDrag: TStartDragEvent; + property OnDragDrop: TDragDropEvent; + property OnDragOver: TDragOverEvent; + property OnEndDrag: TEndDragEvent;*) end; + +function RoundUp(AValue:Single):Integer; +function ResolutionUnitConvert(const AValue:Single; fromRes, toRes:TResolutionUnit; predefInchRes:Integer=96):Single; +procedure PixelXResolutionUnitConvert(var resX, resY:Single; fromRes, toRes:TResolutionUnit); + {$IFDEF FPC}procedure Register;{$ENDIF} implementation @@ -415,6 +564,58 @@ procedure CheckAspectRatio(const Value :String; var AspectRatioText :String; var end; end; +function RoundUp(AValue:Single):Integer; +var + oRoundMode :TFPURoundingMode; + +begin + oRoundMode :=Math.GetRoundMode; + //Round to Upper Value + Math.SetRoundMode(rmUp); + Result :=Round(AValue); + Math.SetRoundMode(oRoundMode); +end; + +function ResolutionUnitConvert(const AValue:Single; fromRes, toRes:TResolutionUnit; predefInchRes:Integer):Single; +begin + if (fromRes<>toRes) + then Case fromRes of + ruNone: begin + if toRes=ruPixelsPerInch + then Result :=AValue/predefInchRes //in + else Result :=(AValue/predefInchRes)*2.54; //cm + end; + ruPixelsPerInch :begin + if toRes=ruPixelsPerCentimeter + then Result :=AValue*2.54 //cm + else Result :=AValue*predefInchRes; //pixel + end; + ruPixelsPerCentimeter :begin + if toRes=ruPixelsPerInch + then Result :=AValue/2.54 //in + else Result :=(AValue/2.54)*predefInchRes;//cm + end; + end + else Result:=AValue; +end; + +procedure PixelXResolutionUnitConvert(var resX, resY: Single; fromRes, toRes: TResolutionUnit); +begin + //Do Conversion from/to PixelXInch/PixelXCm + if (toRes <> fromRes) then + begin + if (toRes=ruPixelsPerInch) + then begin + resX :=resX*2.54; + resY :=resY*2.54; + end + else begin + resX :=resX/2.54; + resY :=resY/2.54; + end + end; +end; + { TCropArea } procedure TCropArea.Render_Refresh; @@ -426,6 +627,25 @@ procedure TCropArea.Render_Refresh; end; end; +procedure TCropArea.GetImageResolution(var resX, resY: Single; var resUnit: TResolutionUnit); +begin + resX :=fOwner.fImageBitmap.ResolutionX; + resY :=fOwner.fImageBitmap.ResolutionY; + resUnit :=fOwner.fImageBitmap.ResolutionUnit; + + if (resX<2) or (resY<2) then //Some images have 1x1 PixelPerInch ? + begin + //No Resolution use predefined Form Values + resUnit :=rAreaUnit; + + if (rAreaUnit=ruPixelsPerInch) + then resX :=fOwner.PixelsPerInch + else resX :=fOwner.PixelsPerInch/2.54; + + resY :=resX; + end; +end; + function TCropArea.getIsNullSize: Boolean; begin Result := not((abs(rArea.Right - rArea.Left) > 0) and (abs(rArea.Bottom - rArea.Top) > 0)); @@ -441,159 +661,323 @@ procedure TCropArea.setName(AValue: String); then fOwner.rOnCropAreaChanged(fOwner, Self); end; -function TCropArea.getTop: Longint; +procedure TCropArea.setIcons(AValue: TCropAreaIcons); +begin + if rIcons=AValue then Exit; + rIcons:=AValue; + Render_Refresh; +end; + +function TCropArea.getTop: Single; begin Result :=rArea.Top; end; -procedure TCropArea.setTop(AValue: Longint); +procedure TCropArea.setTop(AValue: Single); var - tempHeight :Longint; + tempArea:TRectF; begin if AValue=rArea.Top then Exit; - tempHeight :=rArea.Height; - rArea.Top:=AValue; - rArea.Height:=tempHeight; - - CalculateScaledAreaFromArea; - - Render_Refresh; - - if assigned(fOwner.rOnCropAreaChanged) - then fOwner.rOnCropAreaChanged(fOwner, Self); + tempArea :=rArea; + tempArea.Top:=AValue; + tempArea.Height:=rArea.Height; + //CheckAreaOutOfBounds(tempArea); + Area :=tempArea; end; -function TCropArea.getLeft: Longint; +function TCropArea.getLeft: Single; begin Result :=rArea.Left; end; -procedure TCropArea.setLeft(AValue: Longint); +procedure TCropArea.setLeft(AValue: Single); var - tempWidth :Longint; + tempArea:TRectF; + tempSArea:TRect; begin if AValue=rArea.Left then Exit; - tempWidth :=rArea.Width; - rArea.Left:=AValue; - rArea.Width:=tempWidth; - - CalculateScaledAreaFromArea; - - Render_Refresh; + tempArea :=rArea; + tempArea.Left:=AValue; + tempArea.Width:=rArea.Width; + //CheckAreaOutOfBounds(tempArea); + Area :=tempArea; +(* if CheckScaledOutOfBounds(rScaledArea) + then begin + CalculateAreaFromScaledArea; - if assigned(fOwner.rOnCropAreaChanged) - then fOwner.rOnCropAreaChanged(fOwner, Self); + if assigned(fOwner.rOnCropAreaChanged) + then fOwner.rOnCropAreaChanged(fOwner, Self); + end; *) end; -function TCropArea.getHeight: Longint; +function TCropArea.getHeight: Single; begin Result :=rArea.Height; end; -procedure TCropArea.setHeight(AValue: Longint); +procedure TCropArea.setHeight(AValue: Single); var - curKeepAspectRatio :Boolean; - curRatio :TRatio; + tempArea:TRectF; begin if AValue=rArea.Height then Exit; - curKeepAspectRatio :=getRealAspectRatio(curRatio); + tempArea :=rArea; + tempArea.Height:=AValue; + //CheckAreaOutOfBounds(tempArea); + Area :=tempArea; +end; - if curKeepAspectRatio - then begin - //The Height is Changed recalculate the Width - rArea.Width :=Trunc(abs(AValue) * (curRatio.Horizontal / curRatio.Vertical)); - end; +function TCropArea.getWidth: Single; +begin + Result :=rArea.Width; +end; - rArea.Height:=AValue; +procedure TCropArea.setWidth(AValue: Single); +var + tempArea:TRectF; - CalculateScaledAreaFromArea; +begin + if AValue=rArea.Width then Exit; - Render_Refresh; + tempArea :=rArea; + tempArea.Width:=AValue; + //CheckAreaOutOfBounds(tempArea); + Area :=tempArea; +end; - if assigned(fOwner.rOnCropAreaChanged) - then fOwner.rOnCropAreaChanged(fOwner, Self); +function TCropArea.getMaxHeight: Single; +begin + if (rAreaUnit=ruNone) + then Result :=fOwner.fImageBitmap.Height + else begin + if (fOwner.fImageBitmap.ResolutionY<2) + then Result :=fOwner.fImageBitmap.Height //No Resolution, Some images have 1x1 PixelPerInch ? + else begin + Result :=fOwner.fImageBitmap.ResolutionHeight; + + //Do Conversion from/to inch/cm + if (rAreaUnit <> fOwner.fImageBitmap.ResolutionUnit) then + begin + if (rAreaUnit=ruPixelsPerInch) + then Result :=Result/2.54 //Bitmap is in Cm, i'm in Inch + else Result :=Result*2.54; //Bitmap is in Inch, i'm in Cm + end; + end; + end; end; -function TCropArea.getWidth: Longint; +function TCropArea.getMaxWidth: Single; begin - Result :=rArea.Width; + if (rAreaUnit=ruNone) + then Result :=fOwner.fImageBitmap.Width + else begin + if (fOwner.fImageBitmap.ResolutionX<2) + then Result :=fOwner.fImageBitmap.Width //No Resolution, Some images have 1x1 PixelPerInch ? + else begin + Result :=fOwner.fImageBitmap.ResolutionWidth; + + //Do Conversion from/to inch/cm + if (rAreaUnit <> fOwner.fImageBitmap.ResolutionUnit) then + begin + if (rAreaUnit=ruPixelsPerInch) + then Result :=Result/2.54 //Bitmap is in Cm, i'm in Inch + else Result :=Result*2.54; //Bitmap is in Inch, i'm in Cm + end; + end; + end; end; -procedure TCropArea.setWidth(AValue: Longint); +function TCropArea.getIndex: Longint; +begin + Result :=fOwner.CropAreas.IndexOf(Self); +end; + +procedure TCropArea.CalculateScaledAreaFromArea; var - curKeepAspectRatio :Boolean; - curRatio :TRatio; + xRatio, yRatio: Single; + resX, resY: Single; + resUnit:TResolutionUnit; begin - if AValue=rArea.Width then Exit; + if not(isNullSize) then + begin + // Calculate Scaled Area given Scale and Resolution + if (fOwner.fImageBitmap.Width=0) or (fOwner.fImageBitmap.Height=0) + then begin + xRatio :=1; + yRatio :=1; + end + else begin + xRatio := fOwner.fResampledBitmap.Width / fOwner.fImageBitmap.Width; + yRatio := fOwner.fResampledBitmap.Height / fOwner.fImageBitmap.Height; + end; + + resX :=1; //if rAreaUnit=ruNone use only Ratio + resY :=1; - curKeepAspectRatio :=getRealAspectRatio(curRatio); + if (rAreaUnit<>ruNone) then + begin + GetImageResolution(resX, resY, resUnit); + PixelXResolutionUnitConvert(resX, resY, resUnit, rAreaUnit); + end; + + //MaxM: Use Trunc for Top/Left and Round for Right/Bottom so we + // preserve as much data as possible when do the crop + rScaledArea.Left := Trunc(rArea.Left * resX * xRatio); + rScaledArea.Top := Trunc(rArea.Top * resY * yRatio); + rScaledArea.Right := Round(rArea.Right* resX * xRatio); + rScaledArea.Bottom := Round(rArea.Bottom * resY * yRatio); + end; +end; + +procedure TCropArea.CalculateAreaFromScaledArea; +var + xRatio, yRatio: Single; + resX, resY: Single; + resUnit:TResolutionUnit; - if curKeepAspectRatio +begin + // Calculate Scaled Area given Scale and Resolution + if (fOwner.fImageBitmap.Width=0) or (fOwner.fImageBitmap.Height=0) then begin - //The Width is Changed recalculate the Height - rArea.Height :=Trunc(abs(AValue) * (curRatio.Vertical / curRatio.Horizontal)); + xRatio :=1; + yRatio :=1; + end + else begin + xRatio := fOwner.fResampledBitmap.Width / fOwner.fImageBitmap.Width; + yRatio := fOwner.fResampledBitmap.Height / fOwner.fImageBitmap.Height; end; - rArea.Width:=AValue; - - CalculateScaledAreaFromArea; + resX :=1; //if rAreaUnit=ruNone use only Ratio + resY :=1; - Render_Refresh; + if (rAreaUnit<>ruNone) then + begin + GetImageResolution(resX, resY, resUnit); + PixelXResolutionUnitConvert(resX, resY, resUnit, rAreaUnit); + end; - if assigned(fOwner.rOnCropAreaChanged) - then fOwner.rOnCropAreaChanged(fOwner, Self); + rArea.Left := (rScaledArea.Left / resX) / xRatio; + rArea.Right := (rScaledArea.Right / resX) / xRatio; + rArea.Top := (rScaledArea.Top / resY) / yRatio; + rArea.Bottom := (rScaledArea.Bottom / resY) / yRatio; end; -function TCropArea.getIndex: Longint; +function TCropArea.GetPixelArea(const AValue: TRectF): TRect; +var + resX, resY: Single; + resUnit: TResolutionUnit; + begin - Result :=fOwner.CropAreas.IndexOf(Self); + if (rAreaUnit=ruNone) + then begin + Result.Left := Trunc(AValue.Left); + Result.Right := Trunc(AValue.Right); + Result.Top := Trunc(AValue.Top); + Result.Bottom := Trunc(AValue.Bottom); + end + else begin + if (rAreaUnit=ruNone) + then begin + resX :=1; + resY :=1; + end + else GetImageResolution(resX, resY, resUnit); + + PixelXResolutionUnitConvert(resX, resY, resUnit, rAreaUnit); + + Result.Left := Trunc(AValue.Left * resX); + Result.Top := Trunc(AValue.Top * resY); + Result.Right := Round(AValue.Right* resX); + Result.Bottom := Round(AValue.Bottom * resY); + end; end; -procedure TCropArea.CalculateScaledAreaFromArea; +function TCropArea.CheckScaledOutOfBounds(var AArea: TRect): Boolean; var - xRatio, yRatio: double; + tmpValue: Integer; begin - if not(isNullSize) then - begin - { #todo 2 : Test for Null Bitmap } - // Calculate source rectangle in original scale - xRatio := fOwner.fResampledBitmap.Width / fOwner.fImageBitmap.Width; - yRatio := fOwner.fResampledBitmap.Height / fOwner.fImageBitmap.Height; - - rScaledArea.Left := Round(rArea.Left * xRatio); - rScaledArea.Right := Round(rArea.Right * xRatio); - rScaledArea.Top := Round(rArea.Top * yRatio); - rScaledArea.Bottom := Round(rArea.Bottom * yRatio); - end; + Result :=False; + + if (AArea.Left<0) + then begin + tmpValue :=-AArea.Left; + AArea.Left :=0; + AArea.Right:=AArea.Right+tmpValue; + Result :=True; + end; + + if (AArea.Top<0) + then begin + tmpValue :=-AArea.Top; + AArea.Top :=0; + AArea.Bottom:=AArea.Bottom+tmpValue; + Result :=True; + end; + + if (AArea.Right>fOwner.fResampledBitmap.Width) + then begin + tmpValue :=AArea.Right-fOwner.fResampledBitmap.Width; + AArea.Right :=fOwner.fResampledBitmap.Width; + AArea.Left:=AArea.Left-tmpValue; //if <0 ? a vicious circle + Result :=True; + end; + + if (AArea.Bottom>fOwner.fResampledBitmap.Height) + then begin + tmpValue :=AArea.Bottom-fOwner.fResampledBitmap.Height; + AArea.Bottom :=fOwner.fResampledBitmap.Height; + AArea.Top:=AArea.Top-tmpValue; //if <0 ? a vicious circle + Result :=True; + end; end; -procedure TCropArea.CalculateAreaFromScaledArea; +function TCropArea.CheckAreaOutOfBounds(var AArea: TRectF):Boolean; var - xRatio, yRatio: double; + tmpValue, resWH: Single; begin - if not(isNullSize) then - begin - { #todo 2 : Test for Null Bitmap } - // Calculate source rectangle in original scale - xRatio := fOwner.fResampledBitmap.Width / fOwner.fImageBitmap.Width; - yRatio := fOwner.fResampledBitmap.Height / fOwner.fImageBitmap.Height; - - rArea.Left := Round(rScaledArea.Left / xRatio); - rArea.Right := Round(rScaledArea.Right / xRatio); - rArea.Top := Round(rScaledArea.Top / yRatio); - rArea.Bottom := Round(rScaledArea.Bottom / yRatio); - end; -end; + Result :=False; + if (AArea.Left<0) + then begin + tmpValue :=-AArea.Left; + AArea.Left :=0; + AArea.Right:=AArea.Right+tmpValue; + Result :=True; + end; + + if (AArea.Top<0) + then begin + tmpValue :=-AArea.Top; + AArea.Top :=0; + AArea.Bottom:=AArea.Bottom+tmpValue; + Result :=True; + end; + resWH :=fOwner.fImageBitmap.ResolutionWidth; + if (AArea.Right>resWH) + then begin + tmpValue :=AArea.Right-resWH; + AArea.Right :=resWH; + AArea.Left:=AArea.Left-tmpValue; //if <0 ? a vicious circle + Result :=True; + end; + + resWH :=fOwner.fImageBitmap.ResolutionHeight; + if (AArea.Bottom>resWH) + then begin + tmpValue :=AArea.Bottom-resWH; + AArea.Bottom :=resWH; + AArea.Top:=AArea.Top-tmpValue; //if <0 ? a vicious circle + Result :=True; + end; +end; procedure TCropArea.CopyAspectFromParent; begin @@ -675,14 +1059,15 @@ procedure TCropArea.setKeepAspectRatio(AValue: BoolParent); Render_Refresh; end; -procedure TCropArea.setArea(AValue: TRect); +procedure TCropArea.setArea(AValue: TRectF); var curKeepAspectRatio :Boolean; curRatio :TRatio; - calcHeight, calcWidth, swapV :Longint; + calcHeight, calcWidth, swapV :Single; begin - if rArea=AValue then Exit; + if (rArea.TopLeft = AValue.TopLeft) and + (rArea.BottomRight = AValue.BottomRight) then Exit; if (AValue.Left > AValue.Right) then begin @@ -733,6 +1118,94 @@ procedure TCropArea.setArea(AValue: TRect); then fOwner.rOnCropAreaChanged(fOwner, Self); end; +procedure TCropArea.setAreaUnit(AValue: TResolutionUnit); +var + imgResX, imgResY :Single; + +begin + if rAreaUnit=AValue then Exit; + + if not(Loading) and not(isNullSize) then + begin + //Get Image Resolution in Pixel/Inchs + Case fOwner.Bitmap.ResolutionUnit of + ruPixelsPerInch : begin + imgResX :=fOwner.Bitmap.ResolutionX; + imgResY :=fOwner.Bitmap.ResolutionY; + end; + ruPixelsPerCentimeter : begin + imgResX :=fOwner.Bitmap.ResolutionX*2.54; + imgResY :=fOwner.Bitmap.ResolutionY*2.54; + end; + ruNone : begin + //No Image Resolution, Use predefined Monitor Values + imgResX :=fOwner.PixelsPerInch; + imgResY :=fOwner.PixelsPerInch; + end; + end; + + //Paranoid test to avoid zero divisions + if (imgResX=0) then imgResX :=fOwner.PixelsPerInch; + if (imgResY=0) then imgResY :=fOwner.PixelsPerInch; + + Case rAreaUnit of + ruPixelsPerInch : begin + if (AValue=ruNone) + then begin //From Inchs to Pixels, we need Image Resolution + //MaxM: Use Trunc for Top/Left and Round for Right/Bottom so we + // preserve as much data as possible when do the crop + rArea.Left:=Trunc(rArea.Left*imgResX); + rArea.Top:=Trunc(rArea.Top*imgResY); + rArea.Right:=Round(rArea.Right*imgResX); + rArea.Bottom:=Round(rArea.Bottom*imgResY); + end + else begin //From Inchs to Cm + rArea.Left:=rArea.Left*2.54; + rArea.Top:=rArea.Top*2.54; + rArea.Right:=rArea.Right*2.54; + rArea.Bottom:=rArea.Bottom*2.54; + end; + end; + ruPixelsPerCentimeter : begin + if (AValue=ruNone) + then begin //From Cm to Pixels, first convert to Inchs than use Image Resolution + rArea.Left:=Trunc((rArea.Left/2.54)*imgResX); + rArea.Top:=Trunc((rArea.Top/2.54)*imgResY); + rArea.Right:=Round((rArea.Right/2.54)*imgResX); + rArea.Bottom:=Round((rArea.Bottom/2.54)*imgResY); + end + else begin //From Cm to Inchs + rArea.Left:=rArea.Left/2.54; + rArea.Top:=rArea.Top/2.54; + rArea.Right:=rArea.Right/2.54; + rArea.Bottom:=rArea.Bottom/2.54; + end; + end; + ruNone : begin + if (AValue=ruPixelsPerInch) + then begin //From Pixels to Inchs + rArea.Left:=rArea.Left/imgResX; + rArea.Top:=rArea.Top/imgResY; + rArea.Right:=rArea.Right/imgResX; + rArea.Bottom:=rArea.Bottom/imgResY; + end + else begin + rArea.Left:=(rArea.Left/2.54)/imgResX; + rArea.Top:=(rArea.Top/2.54)/imgResY; + rArea.Right:=(rArea.Right/2.54)/imgResX; + rArea.Bottom:=(rArea.Bottom/2.54)/imgResY; + end; + end; + end; + end; + + rAreaUnit:=AValue; + + if assigned(fOwner.rOnCropAreaChanged) + then fOwner.rOnCropAreaChanged(fOwner, Self); +end; + + procedure TCropArea.setScaledArea(AValue: TRect); var curKeepAspectRatio :Boolean; @@ -816,7 +1289,7 @@ function TCropArea.getRealKeepAspectRatio: Boolean; end; //Get Resampled Bitmap (Scaled to current scale) -function TCropArea.getResampledBitmap(OriginalRect :TRect): TBGRABitmap; +function TCropArea.getResampledBitmap: TBGRABitmap; var ResampledBitmap: TBGRACustomBitmap; CropBitmap: TBGRABitmap; @@ -831,9 +1304,6 @@ function TCropArea.getResampledBitmap(OriginalRect :TRect): TBGRABitmap; // Create bitmap to put image on final scale Result := TBGRABitmap.Create(rScaledArea.Width, rScaledArea.Height); - Result.ResolutionUnit:=CropBitmap.ResolutionUnit; - Result.ResolutionX:=CropBitmap.ResolutionX; - Result.ResolutionY:=CropBitmap.ResolutionY; // Resize the cropped image to final scale ResampledBitmap := CropBitmap.Resample(rScaledArea.Width, rScaledArea.Height, rmFineResample); @@ -855,40 +1325,206 @@ function TCropArea.getBitmap: TBGRABitmap; if not (fOwner.fImageBitmap.Empty) then try // Get the cropped image on selected region in original scale - Result :=fOwner.fImageBitmap.GetPart(rArea); - Result.ResolutionUnit:=fOwner.fImageBitmap.ResolutionUnit; - Result.ResolutionX:=fOwner.fImageBitmap.ResolutionX; - Result.ResolutionY:=fOwner.fImageBitmap.ResolutionY; + Result :=fOwner.fImageBitmap.GetPart(GetPixelArea(rArea)); except if (Result<>nil) then FreeAndNil(Result); end; end; -constructor TCropArea.Create(AOwner: TBGRAImageManipulation; AArea :TRect; - ARotate :double = 0; - AUserData : Integer = 0); +constructor TCropArea.Create(AOwner: TBGRAImageManipulation; AArea: TRectF; + AAreaUnit: TResolutionUnit; AUserData: Integer); begin inherited Create; if (AOwner = Nil) - then raise Exception.Create('Owner TBGRAImageManipulation is Nil'); + then raise Exception.Create('TCropArea Owner is Nil'); + OwnerList :=nil; fOwner :=AOwner; + rAreaUnit :=AAreaUnit; Area := AArea; - Rotate := ARotate; - UserData := AUserData; - rAspectX := 3; - rAspectY := 4; - rKeepAspectRatio := bParent; + UserData :=AUserData; + rAspectX :=3; + rAspectY :=4; + rKeepAspectRatio :=bParent; + Loading:=False; CopyAspectFromParent; end; +constructor TCropArea.Create(AOwner: TBGRAImageManipulation; + DuplicateFrom: TCropArea; InsertInList:Boolean); +begin + if (DuplicateFrom = Nil) + then raise Exception.Create('TCropArea DuplicateFrom is Nil'); + + Create(AOwner, DuplicateFrom.Area, DuplicateFrom.AreaUnit, DuplicateFrom.UserData); + + OwnerList :=nil; + rAspectX :=DuplicateFrom.rAspectX; + rAspectY :=DuplicateFrom.rAspectY; + rKeepAspectRatio :=DuplicateFrom.rKeepAspectRatio; + Loading:=False; + if rKeepAspectRatio=bParent + then CopyAspectFromParent; + + if InsertInList and (DuplicateFrom.OwnerList<>nil) + then DuplicateFrom.OwnerList.add(Self); +end; + destructor TCropArea.Destroy; begin inherited Destroy; end; +procedure TCropArea.BringToFront; +begin + if (OwnerList<>nil) then + try + OwnerList.Move(OwnerList.IndexOf(Self), OwnerList.Count-1); + except + end; +end; + +procedure TCropArea.BringToBack; +begin + if (OwnerList<>nil) then + try + OwnerList.Move(OwnerList.IndexOf(Self), 0); + except + end; +end; + +procedure TCropArea.BringForward; +var + curIndex :Integer; + +begin + if (OwnerList<>nil) then + try + curIndex :=OwnerList.IndexOf(Self); + if (curIndexnil) then + try + curIndex :=OwnerList.IndexOf(Self); + if (curIndex>0) + then OwnerList.Move(curIndex, curIndex-1); + except + end; +end; + +procedure TCropArea.RotateLeft; +var + newArea :TRect; + +begin + newArea.Right :=rScaledArea.Left; + newArea.Bottom:=rScaledArea.Bottom; + newArea.Left:=newArea.Right-rScaledArea.Height; + newArea.Top:=newArea.Bottom-rScaledArea.Width; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.RotateRight; +var + newArea :TRect; + +begin + newArea.Left :=rScaledArea.Right; + newArea.Bottom:=rScaledArea.Bottom; + newArea.Right:=newArea.Left+rScaledArea.Height; + newArea.Top:=newArea.Bottom-rScaledArea.Width; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.FlipHLeft; +var + newArea :TRect; + +begin + newArea.Top:=rScaledArea.Top; + newArea.Bottom:=rScaledArea.Bottom; + newArea.Right :=rScaledArea.Left; + newArea.Left:=newArea.Right-rScaledArea.Width; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.FlipHRight; +var + newArea :TRect; + +begin + newArea.Top:=rScaledArea.Top; + newArea.Bottom:=rScaledArea.Bottom; + newArea.Left :=rScaledArea.Right; + newArea.Right:=newArea.Left+rScaledArea.Width; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.FlipVUp; +var + newArea :TRect; + +begin + newArea.Left:=rScaledArea.Left; + newArea.Right:=rScaledArea.Right; + newArea.Bottom :=rScaledArea.Top; + newArea.Top:=newArea.Bottom-rScaledArea.Height; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.FlipVDown; +var + newArea :TRect; + +begin + newArea.Left:=rScaledArea.Left; + newArea.Right:=rScaledArea.Right; + newArea.Top :=rScaledArea.Bottom; + newArea.Bottom:=newArea.Top+rScaledArea.Height; + CheckScaledOutOfBounds(newArea); + ScaledArea :=newArea; +end; + +procedure TCropArea.SetSize(AWidth, AHeight: Single); +var + tempArea:TRectF; + +begin + if (AWidth=rArea.Width) and (AHeight=rArea.Height) + then exit; + + tempArea :=rArea; + tempArea.Width:=AWidth; + tempArea.Height:=AHeight; + //CheckAreaOutOfBounds(tempArea); + Area :=tempArea; +end; + { TCropAreaList } +procedure TCropAreaList.setLoading(AValue: Boolean); +var + i :Integer; + +begin + for i :=0 to Count-1 do items[i].Loading :=AValue; + rLoading:=AValue; +end; + function TCropAreaList.getCropArea(aIndex: Integer): TCropArea; begin Result := inherited Items[aIndex] as TCropArea; @@ -902,10 +1538,16 @@ procedure TCropAreaList.setCropArea(aIndex: Integer; const Value: TCropArea); procedure TCropAreaList.Notify(Ptr: Pointer; Action: TListNotification); begin Case Action of - lnAdded: if assigned(fOwner.rOnCropAreaAdded) - then fOwner.rOnCropAreaAdded(fOwner, Ptr); - lnDeleted: if assigned(fOwner.rOnCropAreaDeleted) - then fOwner.rOnCropAreaDeleted(fOwner, Ptr); + lnAdded: begin + TCropArea(Ptr).OwnerList :=Self; + if assigned(fOwner.rOnCropAreaAdded) + then fOwner.rOnCropAreaAdded(fOwner, Ptr); + end; + lnDeleted: begin + TCropArea(Ptr).OwnerList :=Nil; + if assigned(fOwner.rOnCropAreaDeleted) + then fOwner.rOnCropAreaDeleted(fOwner, Ptr); + end; end; inherited Notify(Ptr, Action); @@ -927,46 +1569,54 @@ function TCropAreaList.add(aCropArea: TCropArea): integer; Result := inherited Add(aCropArea); end; -procedure TCropAreaList.Load(const XMLConf: TXMLConfig); +procedure TCropAreaList.Load(const XMLConf: TXMLConfig; XMLPath: String); var i, newCount, newSelected: integer; - curItemPath: String; + curItemPath, curPath: String; newCropArea: TCropArea; - newArea: TRect; + newArea: TRectF; + newAreaUnit:TResolutionUnit; begin try - loading :=True; + if (XMLPath='') + then curPath :=fOwner.Name+'.'+Self.Name+'/' + else curPath :=XMLPath+'/'; - XMLConf.OpenKey(fOwner.Name+'.'+Self.Name); - newCount := XMLConf.GetValue('Count', -1); + newCount := XMLConf.GetValue(curPath+'Count', -1); if (newCount=-1) - then raise Exception.Create('XML Path not Found'); + then raise Exception.Create('XML Path not Found - '+curPath+'Count'); Clear; + Loading :=True; - newSelected := XMLConf.GetValue('Selected', 0); + newSelected := XMLConf.GetValue(curPath+'Selected', 0); for i :=0 to newCount-1 do begin - curItemPath :='Item' + IntToStr(i); - newArea :=Rect(0,0,0,0); - XMLConf.OpenKey(curItemPath); - XMLConf.OpenKey('Area'); - newArea.Left :=XMLConf.GetValue('Left', 0); - newArea.Top :=XMLConf.GetValue('Top', 0); - newArea.Width :=XMLConf.GetValue('Width', fOwner.MinWidth); - newArea.Height :=XMLConf.GetValue('Height', fOwner.MinHeight); - XMLConf.CloseKey; - newCropArea :=TCropArea.Create(Self.fOwner, newArea); - newCropArea.Name :=XMLConf.GetValue('Name', 'Name '+IntToStr(i)); - newCropArea.KeepAspectRatio :=BoolParent(XMLConf.GetValue('KeepAspectRatio', Integer(bParent))); - newCropArea.AspectRatio :=XMLConf.GetValue('AspectRatio', '3:4'); - newCropArea.Rotate :=StrToFloat(XMLConf.GetValue('Rotate', '0')); - XMLConf.CloseKey; + curItemPath :=curPath+'Item' + IntToStr(i)+'/'; + newArea :=RectF(0,0,0,0); + + //Area + newArea.Left :=StrToFloat(XMLConf.GetValue(curItemPath+'Area/Left', '0')); + newArea.Top :=StrToFloat(XMLConf.GetValue(curItemPath+'Area/Top', '0')); + newArea.Width :=StrToFloat(XMLConf.GetValue(curItemPath+'Area/Width', IntToStr(fOwner.MinWidth))); + newArea.Height :=StrToFloat(XMLConf.GetValue(curItemPath+'Area/Height', IntToStr(fOwner.MinHeight))); + + newAreaUnit :=TResolutionUnit(XMLConf.GetValue(curItemPath+'AreaUnit', 0)); + newCropArea :=TCropArea.Create(Self.fOwner, newArea, newAreaUnit); + newCropArea.Loading:=True; + newCropArea.Name :=XMLConf.GetValue(curItemPath+'Name', 'Name '+IntToStr(i)); + newCropArea.KeepAspectRatio :=BoolParent(XMLConf.GetValue(curItemPath+'KeepAspectRatio', Integer(bParent))); + newCropArea.AspectRatio :=XMLConf.GetValue(curItemPath+'AspectRatio', '3:4'); + newCropArea.Rotate :=StrToFloat(XMLConf.GetValue(curItemPath+'Rotate', '0')); + newCropArea.UserData :=XMLConf.GetValue(curItemPath+'UserData', -1); + + if assigned(fOwner.rOnCropAreaLoad) + then newCropArea.UserData :=fOwner.rOnCropAreaLoad(fOwner, newCropArea, XMLConf, curItemPath); + newCropArea.Loading:=False; add(newCropArea); end; - XmlConf.CloseKey; if (newSelectedrResolutionUnit) then + begin + rResolutionWidth :=ResolutionUnitConvert(rResolutionWidth, rResolutionUnit, AValue, fOwner.PixelsPerInch); + rResolutionHeight :=ResolutionUnitConvert(rResolutionHeight, rResolutionUnit, AValue, fOwner.PixelsPerInch); + rResolutionUnit :=AValue; + end; +end; + +constructor TBGRAEmptyImage.Create(AOwner: TBGRAImageManipulation); +begin + inherited Create; + fOwner :=AOwner; + rAllow :=False; + rShowBorder :=False; + rResolutionUnit:=ruPixelsPerCentimeter; +end; + +{ TBGRANewCropAreaDefault } + +constructor TBGRANewCropAreaDefault.Create(AOwner: TBGRAImageManipulation); +begin + inherited Create; + fOwner :=AOwner; + rKeepAspectRatio:=bFalse; + rAspectRatio:='3:4'; + rResolutionUnit:=ruPixelsPerCentimeter; +end; { TBGRAImageManipulation } @@ -1698,14 +2490,7 @@ function TBGRAImageManipulation.getImageRect(Picture: TBGRABitmap): TRect; { Get work area rectangle } function TBGRAImageManipulation.getWorkRect: TRect; -var - // Number of units to remove from left, right, top, and bottom to get the - // work rectangle - Delta: integer; begin - // Start with the border size - Delta := fBorderSize; - // Get the coordinates of the control if (fVirtualScreen <> nil) then Result := Rect(0, 0, fVirtualScreen.Width, fVirtualScreen.Height) @@ -1713,16 +2498,13 @@ function TBGRAImageManipulation.getWorkRect: TRect; Result := GetClientRect; // Remove the non-work areas from our work rectangle - InflateRect(Result, -Delta, -Delta); + InflateRect(Result, -fBorderSize, -fBorderSize); end; { Check if mouse is over any anchor } function TBGRAImageManipulation.isOverAnchor(APoint :TPoint; var AnchorSelected :TDirection; var ACursor :TCursor):TCropArea; var - rCropArea :TCropArea; - rCropRect, - rCropRectI :TRect; - i :Integer; + i :Integer; function _isOverAnchor(APoint: TPoint; Corner: TPoint): boolean; begin @@ -1732,100 +2514,172 @@ function TBGRAImageManipulation.isOverAnchor(APoint :TPoint; var AnchorSelected (APoint.Y <= (Corner.Y + AnchorSize))); end; -begin - AnchorSelected :=[]; - ACursor :=crDefault; - Result :=Nil; - for i:=0 to rCropAreas.Count-1 do + function TestArea(rCropArea :TCropArea):TCropArea; + var + rCropRect, + rCropRectI :TRect; + + begin + Result :=nil; + rCropRectI :=rCropArea.ScaledArea; + InflateRect(rCropRectI, AnchorSize, AnchorSize); + if ({$IFNDEF FPC}BGRAGraphics.{$ENDIF}PtInRect(rCropRectI, APoint)) then begin - rCropArea :=rCropAreas[i]; - rCropRectI :=rCropArea.ScaledArea; - InflateRect(rCropRectI, AnchorSize, AnchorSize); - if ({$IFNDEF FPC}BGRAGraphics.{$ENDIF}PtInRect(rCropRectI, APoint)) then + rCropRect :=rCropArea.ScaledArea; + // Verifies that is positioned on an anchor + // NW + if (_isOverAnchor(APoint, rCropRect.TopLeft)) then begin - rCropRect :=rCropArea.ScaledArea; - // Verifies that is positioned on an anchor - // NW - if (_isOverAnchor(APoint, rCropRect.TopLeft)) then - begin - AnchorSelected := [NORTH, WEST]; - ACursor := crSizeNW; - Result :=rCropArea; break; - end; + AnchorSelected := [NORTH, WEST]; + ACursor := crSizeNW; + Result :=rCropArea; exit; + end; - // W - if (_isOverAnchor(APoint, Point(rCropRect.Left, rCropRect.Top + - (rCropRect.Bottom - rCropRect.Top) div 2))) then - begin - AnchorSelected := [WEST]; - ACursor := crSizeWE; - Result :=rCropArea; break; - end; + // W + if (_isOverAnchor(APoint, Point(rCropRect.Left, rCropRect.Top + + (rCropRect.Bottom - rCropRect.Top) div 2))) then + begin + AnchorSelected := [WEST]; + ACursor := crSizeWE; + Result :=rCropArea; exit; + end; - // SW - if (_isOverAnchor(APoint, Point(rCropRect.Left, rCropRect.Bottom))) then - begin - AnchorSelected := [SOUTH, WEST]; - ACursor := crSizeSW; - Result :=rCropArea; break; - end; + // SW + if (_isOverAnchor(APoint, Point(rCropRect.Left, rCropRect.Bottom))) then + begin + AnchorSelected := [SOUTH, WEST]; + ACursor := crSizeSW; + Result :=rCropArea; exit; + end; - // S - if (_isOverAnchor(APoint, Point(rCropRect.Left + - ((rCropRect.Right - rCropRect.Left) div 2), rCropRect.Bottom))) then - begin - AnchorSelected := [SOUTH]; - ACursor := crSizeNS; - Result :=rCropArea; break; - end; + // S + if (_isOverAnchor(APoint, Point(rCropRect.Left + + ((rCropRect.Right - rCropRect.Left) div 2), rCropRect.Bottom))) then + begin + AnchorSelected := [SOUTH]; + ACursor := crSizeNS; + Result :=rCropArea; exit; + end; - // SE - if (_isOverAnchor(APoint, rCropRect.BottomRight)) then - begin - AnchorSelected := [SOUTH, EAST]; - ACursor := crSizeSE; - Result :=rCropArea; break; - end; + // SE + if (_isOverAnchor(APoint, rCropRect.BottomRight)) then + begin + AnchorSelected := [SOUTH, EAST]; + ACursor := crSizeSE; + Result :=rCropArea; exit; + end; - // E - if (_isOverAnchor(APoint, Point(rCropRect.Right, rCropRect.Top + - ((rCropRect.Bottom - rCropRect.Top) div 2)))) then - begin - AnchorSelected := [EAST]; - ACursor := crSizeWE; - Result :=rCropArea; break; - end; + // E + if (_isOverAnchor(APoint, Point(rCropRect.Right, rCropRect.Top + + ((rCropRect.Bottom - rCropRect.Top) div 2)))) then + begin + AnchorSelected := [EAST]; + ACursor := crSizeWE; + Result :=rCropArea; exit; + end; - // NE - if (_isOverAnchor(APoint, Point(rCropRect.Right, rCropRect.Top))) then - begin - AnchorSelected := [NORTH, EAST]; - ACursor := crSizeNE; - Result :=rCropArea; break; - end; + // NE + if (_isOverAnchor(APoint, Point(rCropRect.Right, rCropRect.Top))) then + begin + AnchorSelected := [NORTH, EAST]; + ACursor := crSizeNE; + Result :=rCropArea; exit; + end; - // N - if (_isOverAnchor(APoint, Point(rCropRect.Left + - ((rCropRect.Right - rCropRect.Left) div 2), rCropRect.Top))) then - begin - AnchorSelected := [NORTH]; - ACursor := crSizeNS; - Result :=rCropArea; break; - end; + // N + if (_isOverAnchor(APoint, Point(rCropRect.Left + + ((rCropRect.Right - rCropRect.Left) div 2), rCropRect.Top))) then + begin + AnchorSelected := [NORTH]; + ACursor := crSizeNS; + Result :=rCropArea; exit; + end; - // Verifies that is positioned on a cropping area - if (AnchorSelected = []) then + // Verifies that is positioned on a cropping area + if (AnchorSelected = []) then + begin + if ((APoint.X >= rCropRect.Left) and (APoint.X <= rCropRect.Right) and + (APoint.Y >= rCropRect.Top) and (APoint.Y <= rCropRect.Bottom)) then begin - if ((APoint.X >= rCropRect.Left) and (APoint.X <= rCropRect.Right) and - (APoint.Y >= rCropRect.Top) and (APoint.Y <= rCropRect.Bottom)) then - begin - AnchorSelected := [NORTH, SOUTH, EAST, WEST]; - ACursor := crSizeAll; - Result :=rCropArea; break; - end; + AnchorSelected := [NORTH, SOUTH, EAST, WEST]; + ACursor := crSizeAll; + Result :=rCropArea; exit; end; end; - end; + end; + end; + +begin + AnchorSelected :=[]; + ACursor :=crDefault; + Result :=Nil; + if (SelectedCropArea=nil) + then for i:=rCropAreas.Count-1 downto 0 do //downto so respect ZOrder + begin + Result :=TestArea(rCropAreas[i]); + if (Result<>nil) then break; + end + else begin + //Gives precedence to the selected area + Result :=TestArea(SelectedCropArea); + if (Result=nil) then + for i:=rCropAreas.Count-1 downto 0 do + begin + if (rCropAreas[i]<>SelectedCropArea) then + begin + Result :=TestArea(rCropAreas[i]); + if (Result<>nil) then break; + end; + end; + end; +end; + +procedure TBGRAImageManipulation.CreateEmptyImage; +begin + fImageBitmap.Free; + fImageBitmap :=TBGRABitmap.Create(EmptyImage.Width, EmptyImage.Height); + fImageBitmap.ResolutionUnit :=ruPixelsPerInch; + fImageBitmap.ResolutionX :=Self.PixelsPerInch; + fImageBitmap.ResolutionY :=fImageBitmap.ResolutionX; +end; + +procedure TBGRAImageManipulation.CreateResampledBitmap; +var + DestinationRect: TRect; + ResampledBitmap: TBGRACustomBitmap; + +begin + // Get the resampled dimensions to scale image for draw in component + DestinationRect := getImageRect(fImageBitmap); + + // Recreate resampled bitmap + try + fResampledBitmap.Free; + fResampledBitmap := TBGRABitmap.Create(DestinationRect.Right - DestinationRect.Left, + DestinationRect.Bottom - DestinationRect.Top); + ResampledBitmap := fImageBitmap.Resample(DestinationRect.Right - DestinationRect.Left, + DestinationRect.Bottom - DestinationRect.Top, rmFineResample); + fResampledBitmap.BlendImage(0, 0, ResampledBitmap, boLinearBlend); + finally + ResampledBitmap.Free; + end; +end; + +procedure TBGRAImageManipulation.Loaded; +begin + inherited Loaded; + + if Self.Empty and rEmptyImage.Allow then + begin + CreateEmptyImage; + CreateResampledBitmap; + end; + + rLoading:=False; + + // Force Render Struct + RepaintBackground; + Render; end; { ============================================================================ } @@ -1839,6 +2693,9 @@ constructor TBGRAImageManipulation.Create(AOwner: TComponent); begin inherited Create(AOwner); + //MaxM: csLoading in ComponentState does not work? + rLoading :=True; + // Set default component values inherited Width := 320; inherited Height := 240; @@ -1859,7 +2716,6 @@ constructor TBGRAImageManipulation.Create(AOwner: TComponent); // Calculate the ratio fGCD := getGCD(fAspectX, fAspectY); - // Determine the ratio of scale per axle with fRatio do begin @@ -1882,16 +2738,15 @@ constructor TBGRAImageManipulation.Create(AOwner: TComponent); // Create render surface fVirtualScreen := TBGRABitmap.Create(Width, Height); + rEmptyImage :=TBGRAEmptyImage.Create(Self); + rNewCropAreaDefault :=TBGRANewCropAreaDefault.Create(Self); + // Initialize crop area rCropAreas :=TCropAreaList.Create(Self); rCropAreas.Name:='CropAreas'; rNewCropArea :=Nil; rSelectedCropArea :=Nil; - // Force Render Struct - RepaintBackground; - Render; - fMouseCaught := False; end; @@ -1901,6 +2756,8 @@ destructor TBGRAImageManipulation.Destroy; fResampledBitmap.Free; fBackground.Free; fVirtualScreen.Free; + rEmptyImage.Free; + rNewCropAreaDefault.Free; rCropAreas.Free; inherited Destroy; @@ -2002,52 +2859,35 @@ procedure TBGRAImageManipulation.Resize; end; var - DestinationRect: TRect; - ResampledBitmap:TBGRACustomBitmap; i :Integer; curCropArea :TCropArea; begin inherited Resize; + //MaxM: Maybe csLoading in ComponentState but it does not work + if rLoading then exit; + if (fVirtualScreen <> nil) then begin fVirtualScreen.SetSize(min(Self.Width, (fBorderSize * 2 + fAnchorSize + fMinWidth)), min(Self.Height, (fBorderSize * 2 + fAnchorSize + fMinHeight))); fVirtualScreen.InvalidateBitmap; - // Resample the image - if (not (fImageBitmap.Empty)) then + if Self.Empty and rEmptyImage.Allow + then CreateEmptyImage; + + CreateResampledBitmap; + + for i:=0 to rCropAreas.Count-1 do begin - // Get the resampled dimensions to scale image for draw in component - DestinationRect := getImageRect(fImageBitmap); + curCropArea :=rCropAreas[i]; + curCropArea.CalculateScaledAreaFromArea; - for i:=0 to rCropAreas.Count-1 do + if curCropArea.isNullSize then begin - curCropArea :=rCropAreas[i]; - curCropArea.CalculateScaledAreaFromArea; - (* - if curCropArea.isNullSize then - begin begin - // A Null-size crop selection - //delCropArea(curCropArea); ? - end; - *) - end; - - // Recreate resampled bitmap - try - fResampledBitmap.Free; - fResampledBitmap := TBGRABitmap.Create(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top); - ResampledBitmap := fImageBitmap.Resample(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - - DestinationRect.Top, rmFineResample); - fResampledBitmap.BlendImage(0, 0, - ResampledBitmap, - boLinearBlend); - finally - ResampledBitmap.Free; + // A Null-size crop selection (delete it or assign max size?) + //CalcMaxSelection(curCropArea); end; end; @@ -2064,12 +2904,14 @@ procedure TBGRAImageManipulation.Resize; different transparency level for easy viewing of what will be cut. } procedure TBGRAImageManipulation.Render; var - WorkRect: TRect; + WorkRect, emptyRect: TRect; Mask: TBGRABitmap; - BorderColor, SelectColor, FillColor: TBGRAPixel; + BorderColor, SelectColor, + FillColor, IcoColor: TBGRAPixel; curCropArea :TCropArea; curCropAreaRect :TRect; - i :Integer; + i: Integer; + TextS:TTextStyle; begin // This procedure render main feature of engine @@ -2078,79 +2920,108 @@ procedure TBGRAImageManipulation.Render; fVirtualScreen.BlendImage(0, 0, fBackground, boLinearBlend); // Render the image - if (not (fImageBitmap.Empty)) then - begin - // Find the working area of the component - WorkRect := getWorkRect; + // Find the working area of the component + WorkRect := getWorkRect; - try - // Draw image - fVirtualScreen.BlendImage(WorkRect.Left, WorkRect.Top, fResampledBitmap, boLinearBlend); + try + // Draw image + fVirtualScreen.BlendImage(WorkRect.Left, WorkRect.Top, fResampledBitmap, boLinearBlend); - // Render the selection background area - BorderColor := BGRAWhite; - FillColor := BGRA(0, 0, 0, 128); - Mask := TBGRABitmap.Create(WorkRect.Right - WorkRect.Left, WorkRect.Bottom - WorkRect.Top, FillColor); + // Render the selection background area + BorderColor := BGRAWhite; + FillColor := BGRA(0, 0, 0, 128); + Mask := TBGRABitmap.Create(WorkRect.Right - WorkRect.Left, WorkRect.Bottom - WorkRect.Top, FillColor); - for i:=0 to rCropAreas.Count-1 do - begin - curCropArea :=rCropAreas[i]; - curCropAreaRect :=curCropArea.ScaledArea; + if Self.Empty and rEmptyImage.Allow and rEmptyImage.ShowBorder then + begin + emptyRect :=Rect(0,0,fResampledBitmap.Width-1, fResampledBitmap.Height-1); + Mask.CanvasBGRA.Frame3d(emptyRect, 1, bvRaised, BGRA(255, 255, 255, 180), BGRA(0, 0, 0, 160)); + //Mask.Rectangle(emptyRect, BorderColor, BGRAPixelTransparent); //wich one? + end; + + for i:=0 to rCropAreas.Count-1 do + begin + curCropArea :=rCropAreas[i]; + curCropAreaRect :=curCropArea.ScaledArea; - if (curCropArea = SelectedCropArea) - then BorderColor := BGRA(255, 0, 0, 255) - else if (curCropArea = rNewCropArea) + //Colors + SelectColor := BGRA(255, 255, 0, 255); + FillColor := BGRA(255, 255, 0, 128); + + if (curCropArea = SelectedCropArea) + then begin + BorderColor := BGRA(255, 0, 0, 255); + IcoColor :=BorderColor; + end + else begin + if (curCropArea = rNewCropArea) then BorderColor := BGRA(255, 0, 255, 255) else BorderColor := curCropArea.BorderColor; - Mask.EraseRectAntialias(curCropAreaRect.Left, curCropAreaRect.Top, curCropAreaRect.Right-1, - curCropAreaRect.Bottom-1, 255); + IcoColor :=SelectColor; + end; + + Mask.EraseRectAntialias(curCropAreaRect.Left, curCropAreaRect.Top, curCropAreaRect.Right-1, + curCropAreaRect.Bottom-1, 255); - // Draw a selection box - with Rect(curCropAreaRect.Left, curCropAreaRect.Top, curCropAreaRect.Right-1, curCropAreaRect.Bottom-1) do + // Draw a selection box + with Rect(curCropAreaRect.Left, curCropAreaRect.Top, curCropAreaRect.Right-1, curCropAreaRect.Bottom-1) do Mask.DrawPolyLineAntialias([Point(Left, Top), Point(Right, Top), Point(Right, Bottom), Point(Left, Bottom), Point(Left, Top)], BorderColor, BGRAPixelTransparent, 1, False); - // Draw anchors - BorderColor := BGRABlack; - SelectColor := BGRA(255, 255, 0, 255); - FillColor := BGRA(255, 255, 0, 128); + //Draw Icons + if (cIcoIndex in curCropArea.Icons) then + begin + TextS.Alignment:=taCenter; + TextS.SystemFont:=True; + TextS.Layout:=tlCenter; + TextS.SingleLine:=True; + Mask.FontHeight:=12; + Mask.FontStyle:=[fsBold]; + Mask.EllipseAntialias(curCropAreaRect.Right-12, curCropAreaRect.Top+12, 4,4, IcoColor, 8); + Mask.TextRect(Rect(curCropAreaRect.Right-18, curCropAreaRect.Top+2, curCropAreaRect.Right-4, curCropAreaRect.Top+24), + curCropAreaRect.Right-12, curCropAreaRect.Top+12, + IntToStr(curCropArea.getIndex), TextS, BGRAWhite); + end; + + // Draw anchors + BorderColor := BGRABlack; - // NW - Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, curCropAreaRect.Top-fAnchorSize, + // NW + Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, curCropAreaRect.Top-fAnchorSize, curCropAreaRect.Left+fAnchorSize+1, curCropAreaRect.Top+fAnchorSize+1, BorderColor, FillColor, dmSet); - // W - Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, + // W + Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, (curCropAreaRect.Top+((curCropAreaRect.Bottom - curCropAreaRect.Top) div 2))-fAnchorSize, curCropAreaRect.Left+fAnchorSize+1, (curCropAreaRect.Top+((curCropAreaRect.Bottom - curCropAreaRect.Top) div 2))+fAnchorSize+1, BorderColor, FillColor, dmSet); - // SW - Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, curCropAreaRect.Bottom-fAnchorSize-1, + // SW + Mask.Rectangle(curCropAreaRect.Left-fAnchorSize, curCropAreaRect.Bottom-fAnchorSize-1, curCropAreaRect.Left+fAnchorSize+1, curCropAreaRect.Bottom+fAnchorSize, BorderColor, FillColor, dmSet); - // S - if ((fAnchorSelected = [NORTH]) and (curCropAreaRect.Top < curCropAreaRect.Bottom) and + // S + if ((fAnchorSelected = [NORTH]) and (curCropAreaRect.Top < curCropAreaRect.Bottom) and (fStartPoint.Y = curCropAreaRect.Top)) or ((fAnchorSelected = [NORTH]) and (curCropAreaRect.Top > curCropAreaRect.Bottom) and (fStartPoint.Y = curCropAreaRect.Top)) or ((fAnchorSelected = [SOUTH]) and (curCropAreaRect.Top < curCropAreaRect.Bottom) and (fStartPoint.Y = curCropAreaRect.Top)) or ((fAnchorSelected = [SOUTH]) and (curCropAreaRect.Top > curCropAreaRect.Bottom) and (fStartPoint.Y = curCropAreaRect.Top)) - then Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, + then Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, curCropAreaRect.Bottom-fAnchorSize-1, (curCropAreaRect.Left+((curCropAreaRect.Right - curCropAreaRect.Left) div 2))+fAnchorSize+1, curCropAreaRect.Bottom+fAnchorSize, BorderColor, SelectColor, dmSet) - else Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, + else Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, curCropAreaRect.Bottom-fAnchorSize-1, (curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))+fAnchorSize+1, curCropAreaRect.Bottom+fAnchorSize, BorderColor, FillColor, dmSet); - // SE - if ((fAnchorSelected = [NORTH, WEST]) and + // SE + if ((fAnchorSelected = [NORTH, WEST]) and ((curCropAreaRect.Left > curCropAreaRect.Right) and (curCropAreaRect.Top > curCropAreaRect.Bottom))) or ((fAnchorSelected = [NORTH, WEST]) and ((curCropAreaRect.Left < curCropAreaRect.Right) and (curCropAreaRect.Top < curCropAreaRect.Bottom))) or @@ -2182,43 +3053,42 @@ procedure TBGRAImageManipulation.Render; ((curCropAreaRect.Left > curCropAreaRect.Right) and (curCropAreaRect.Top > curCropAreaRect.Bottom))) or ((fAnchorSelected = [SOUTH, WEST]) and ((curCropAreaRect.Left < curCropAreaRect.Right) and (curCropAreaRect.Top < curCropAreaRect.Bottom))) - then Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, + then Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, curCropAreaRect.Bottom-fAnchorSize-1, curCropAreaRect.Right+fAnchorSize, curCropAreaRect.Bottom+fAnchorSize, BorderColor, SelectColor, dmSet) - else Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, + else Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, curCropAreaRect.Bottom-fAnchorSize-1, curCropAreaRect.Right+fAnchorSize, curCropAreaRect.Bottom+fAnchorSize, BorderColor, FillColor, dmSet); - // E - if ((fAnchorSelected = [EAST]) and (curCropAreaRect.Left < curCropAreaRect.Right) and + // E + if ((fAnchorSelected = [EAST]) and (curCropAreaRect.Left < curCropAreaRect.Right) and (fStartPoint.X = curCropAreaRect.Left)) or ((fAnchorSelected = [EAST]) and (curCropAreaRect.Left > curCropAreaRect.Right) and (fStartPoint.X = curCropAreaRect.Left)) or ((fAnchorSelected = [WEST]) and (curCropAreaRect.Left < curCropAreaRect.Right) and (fStartPoint.X = curCropAreaRect.Left)) or ((fAnchorSelected = [WEST]) and (curCropAreaRect.Left > curCropAreaRect.Right) and (fStartPoint.X = curCropAreaRect.Left)) - then Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, + then Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, (curCropAreaRect.Top+((curCropAreaRect.Bottom - curCropAreaRect.Top) div 2))-fAnchorSize, curCropAreaRect.Right+fAnchorSize, (curCropAreaRect.Top+((curCropAreaRect.Bottom-curCropAreaRect.Top) div 2))+fAnchorSize+1, BorderColor, SelectColor, dmSet) - else Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, (curCropAreaRect.Top+((curCropAreaRect.Bottom-curCropAreaRect.Top) div 2))-fAnchorSize, + else Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, (curCropAreaRect.Top+((curCropAreaRect.Bottom-curCropAreaRect.Top) div 2))-fAnchorSize, curCropAreaRect.Right+fAnchorSize, (curCropAreaRect.Top+((curCropAreaRect.Bottom-curCropAreaRect.Top) div 2))+fAnchorSize+1, BorderColor, FillColor, dmSet); - // NE - Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, curCropAreaRect.Top-fAnchorSize, + // NE + Mask.Rectangle(curCropAreaRect.Right-fAnchorSize-1, curCropAreaRect.Top-fAnchorSize, curCropAreaRect.Right+fAnchorSize, curCropAreaRect.Top+fAnchorSize+1, BorderColor, FillColor, dmSet); - // N - Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, + // N + Mask.Rectangle((curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))-fAnchorSize, curCropAreaRect.Top-fAnchorSize, (curCropAreaRect.Left+((curCropAreaRect.Right-curCropAreaRect.Left) div 2))+fAnchorSize+1, curCropAreaRect.Top+fAnchorSize+1, BorderColor, FillColor, dmSet); - end; - finally - fVirtualScreen.BlendImage(WorkRect.Left, WorkRect.Top, Mask, boLinearBlend); - Mask.Free; end; + finally + fVirtualScreen.BlendImage(WorkRect.Left, WorkRect.Top, Mask, boLinearBlend); + Mask.Free; end; end; @@ -2231,6 +3101,13 @@ function TBGRAImageManipulation.getAnchorSize: byte; Result := fAnchorSize * 2 + 1; end; +function TBGRAImageManipulation.getPixelsPerInch: Integer; +begin + if (Owner is TCustomForm) + then Result :=TCustomForm(Owner).PixelsPerInch + else Result :=96; +end; + procedure TBGRAImageManipulation.setAnchorSize(const Value: byte); const MinSize = 3; @@ -2269,7 +3146,7 @@ procedure TBGRAImageManipulation.setAnchorSize(const Value: byte); function TBGRAImageManipulation.getEmpty: boolean; begin - Result := fImageBitmap.Empty; + Result := fImageBitmap.Empty or (fImageBitmap.Width = 0) or (fImageBitmap.Height = 0); end; function TBGRAImageManipulation.getResampledBitmap(ACropArea :TCropArea = Nil): TBGRABitmap; @@ -2278,9 +3155,9 @@ function TBGRAImageManipulation.getResampledBitmap(ACropArea :TCropArea = Nil): if not (fImageBitmap.Empty) then begin if (ACropArea = Nil) - then ACropArea := Self.SelectedCropArea; + then ACropArea := Self.SelectedCropArea; if (ACropArea <> Nil) - then Result :=ACropArea.getResampledBitmap(getImageRect(fImageBitmap)); + then Result :=ACropArea.getResampledBitmap; end; end; @@ -2298,101 +3175,40 @@ function TBGRAImageManipulation.getBitmap(ACropArea :TCropArea = Nil): TBGRABitm end; procedure TBGRAImageManipulation.setBitmap(const Value: TBGRABitmap); - - function min(const Value: integer; const MinValue: integer): integer; - begin - if (Value < MinValue) then - Result := MinValue - else - Result := Value; - end; - var - SourceRect, OriginalRect, DestinationRect: TRect; - ResampledBitmap: TBGRACustomBitmap; - xRatio, yRatio: double; - curCropArea :TCropArea; - curCropAreaRect :TRect; - i :Integer; + curCropArea: TCropArea; + i: Integer; begin if (Value <> fImageBitmap) then begin try - // Clear actual image - fImageBitmap.Free; - fImageBitmap := TBGRABitmap.Create(Value.Width, Value.Height); - - // Prevent empty image - if Value.Empty then - exit; - - // Prevent null image - if (Value.Width = 0) or (Value.Height = 0) then - exit; - - // Associate the new bitmap - fImageBitmap.Assign(Value); - - // Get the resampled dimensions to scale image for draw in component - DestinationRect := getImageRect(fImageBitmap); - - // Recreate resampled bitmap - try - fResampledBitmap.Free; - fResampledBitmap := TBGRABitmap.Create(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top); - ResampledBitmap := fImageBitmap.Resample(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - - DestinationRect.Top, rmFineResample); - fResampledBitmap.BlendImage(0, 0, - ResampledBitmap, - boLinearBlend); - finally - ResampledBitmap.Free; - end; + if Value.Empty or (Value.Width = 0) or (Value.Height = 0) + then begin + if EmptyImage.Allow + then CreateEmptyImage + else exit; + end + else begin + // Clear actual image + fImageBitmap.Free; + fImageBitmap :=TBGRABitmap.Create(Value.Width, Value.Height); + + fImageBitmap.Assign(Value); // Associate the new bitmap + end; + + CreateResampledBitmap; - // Calculate scale from original size and destination size - with OriginalRect do - begin - Left := 0; - Right := fResampledBitmap.Width; - Top := 0; - Bottom := fResampledBitmap.Height; - end; for i:=0 to rCropAreas.Count-1 do begin curCropArea :=rCropAreas[i]; - curCropAreaRect :=curCropArea.ScaledArea; + curCropArea.CalculateScaledAreaFromArea; - // Resize crop area - if ((abs(curCropAreaRect.Right - curCropAreaRect.Left) > 0) and - (abs(curCropAreaRect.Bottom - curCropAreaRect.Top) > 0)) then - begin - // Calculate source rectangle in original scale - xRatio := fImageBitmap.Width / (OriginalRect.Right - OriginalRect.Left); - yRatio := fImageBitmap.Height / (OriginalRect.Bottom - OriginalRect.Top); - with SourceRect do + if curCropArea.isNullSize then begin - Left := Round(curCropAreaRect.Left * xRatio); - Right := Round(curCropAreaRect.Right * xRatio); - Top := Round(curCropAreaRect.Top * yRatio); - Bottom := Round(curCropAreaRect.Bottom * yRatio); + // A Null-size crop selection (delete it or assign max size?) + //CalcMaxSelection(curCropArea); end; - - // Calculate destination rectangle in new scale - xRatio := fImageBitmap.Width / (DestinationRect.Right - DestinationRect.Left); - yRatio := fImageBitmap.Height / (DestinationRect.Bottom - DestinationRect.Top); - curCropArea.ScaledArea :=Rect(Round(SourceRect.Left / xRatio), - Round(SourceRect.Top / yRatio), - Round(SourceRect.Right / xRatio), - Round(SourceRect.Bottom / yRatio)); - end - else - begin - // A Null-size crop selection (delete it or assign max size?) - //CalcMaxSelection(curCropArea); - end; end; finally // Force Render Struct @@ -2404,82 +3220,33 @@ procedure TBGRAImageManipulation.setBitmap(const Value: TBGRABitmap); procedure TBGRAImageManipulation.rotateLeft; var - SourceRect, OriginalRect, DestinationRect: TRect; - TempBitmap, ResampledBitmap: TBGRACustomBitmap; - xRatio, yRatio: double; + TempBitmap: TBGRACustomBitmap; curCropArea :TCropArea; - curCropAreaRect :TRect; i :Integer; begin try - // Prevent empty image - if fImageBitmap.Empty then - exit; + // Prevent empty image if not Allowed + if Self.Empty and not(rEmptyImage.Allow) + then exit; // Rotate bitmap TempBitmap := fImageBitmap.RotateCCW; fImageBitmap.Assign(TempBitmap); - // Get the resampled dimensions to scale image for draw in component - DestinationRect := getImageRect(fImageBitmap); - - // Recreate resampled bitmap - try - fResampledBitmap.Free; - fResampledBitmap := TBGRABitmap.Create(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top); - ResampledBitmap := fImageBitmap.Resample(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top, - rmFineResample); - fResampledBitmap.BlendImage(0, 0, - ResampledBitmap, - boLinearBlend); - finally - ResampledBitmap.Free; - end; + CreateResampledBitmap; - // Calculate scale from original size and destination size - with OriginalRect do - begin - Left := 0; - Right := fResampledBitmap.Width; - Top := 0; - Bottom := fResampledBitmap.Height; - end; + { #todo -oMaxM : Rotate the Crop Areas? a bool published property? } for i:=0 to rCropAreas.Count-1 do begin curCropArea :=rCropAreas[i]; - curCropAreaRect :=curCropArea.ScaledArea; + curCropArea.CalculateScaledAreaFromArea; - // Resize crop area - if ((abs(curCropAreaRect.Right - curCropAreaRect.Left) > 0) and - (abs(curCropAreaRect.Bottom - curCropAreaRect.Top) > 0)) then - begin - // Calculate source rectangle in original scale - xRatio := fImageBitmap.Width / (OriginalRect.Right - OriginalRect.Left); - yRatio := fImageBitmap.Height / (OriginalRect.Bottom - OriginalRect.Top); - with SourceRect do + if curCropArea.isNullSize then begin - Left := Round(curCropAreaRect.Left * xRatio); - Right := Round(curCropAreaRect.Right * xRatio); - Top := Round(curCropAreaRect.Top * yRatio); - Bottom := Round(curCropAreaRect.Bottom * yRatio); + // A Null-size crop selection (delete it or assign max size?) + //CalcMaxSelection(curCropArea); end; - - // Calculate destination rectangle in new scale - xRatio := fImageBitmap.Width / (DestinationRect.Right - DestinationRect.Left); - yRatio := fImageBitmap.Height / (DestinationRect.Bottom - DestinationRect.Top); - curCropArea.ScaledArea :=Rect(Round(SourceRect.Left / xRatio), - Round(SourceRect.Top / yRatio), - Round(SourceRect.Right / xRatio), - Round(SourceRect.Bottom / yRatio)); - end - else - begin - // A Null-size crop selection (delete it or assign max size?) - //CalcMaxSelection(curCropArea); - end; end; finally // Force Render Struct @@ -2491,83 +3258,33 @@ procedure TBGRAImageManipulation.rotateLeft; procedure TBGRAImageManipulation.rotateRight; var - SourceRect, OriginalRect, DestinationRect: TRect; - TempBitmap, ResampledBitmap: TBGRACustomBitmap; - xRatio, yRatio: double; + TempBitmap: TBGRACustomBitmap; curCropArea :TCropArea; - curCropAreaRect :TRect; i :Integer; begin try - // Prevent empty image - if fImageBitmap.Empty then - exit; + // Prevent empty image if not Allowed + if Self.Empty and not(rEmptyImage.Allow) + then exit; // Rotate bitmap TempBitmap := fImageBitmap.RotateCW; fImageBitmap.Assign(TempBitmap); - // Get the resampled dimensions to scale image for draw in component - DestinationRect := getImageRect(fImageBitmap); - - // Recreate resampled bitmap - try - fResampledBitmap.Free; - fResampledBitmap := TBGRABitmap.Create(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top); - ResampledBitmap := fImageBitmap.Resample(DestinationRect.Right - - DestinationRect.Left, DestinationRect.Bottom - DestinationRect.Top, - rmFineResample); - fResampledBitmap.BlendImage(0, 0, - ResampledBitmap, - boLinearBlend); - finally - ResampledBitmap.Free; - end; + CreateResampledBitmap; - // Calculate scale from original size and destination size - with OriginalRect do - begin - Left := 0; - Right := fResampledBitmap.Width; - Top := 0; - Bottom := fResampledBitmap.Height; - end; + { #todo -oMaxM : Rotate the Crop Areas? a bool published property? } for i:=0 to rCropAreas.Count-1 do begin curCropArea :=rCropAreas[i]; - curCropAreaRect :=curCropArea.ScaledArea; + curCropArea.CalculateScaledAreaFromArea; - // Resize crop area - if ((abs(curCropAreaRect.Right - curCropAreaRect.Left) > 0) and - (abs(curCropAreaRect.Bottom - curCropAreaRect.Top) > 0)) then - begin - // Calculate source rectangle in original scale - xRatio := fImageBitmap.Width / (OriginalRect.Right - OriginalRect.Left); - yRatio := fImageBitmap.Height / (OriginalRect.Bottom - OriginalRect.Top); - with SourceRect do + if curCropArea.isNullSize then begin - Left := Round(curCropAreaRect.Left * xRatio); - Right := Round(curCropAreaRect.Right * xRatio); - Top := Round(curCropAreaRect.Top * yRatio); - Bottom := Round(curCropAreaRect.Bottom * yRatio); + // A Null-size crop selection (delete it or assign max size?) + //CalcMaxSelection(curCropArea); end; - - // Calculate destination rectangle in new scale - xRatio := fImageBitmap.Width / (DestinationRect.Right - DestinationRect.Left); - yRatio := fImageBitmap.Height / (DestinationRect.Bottom - DestinationRect.Top); - curCropArea.ScaledArea :=Rect(Round(SourceRect.Left / xRatio), - Round(SourceRect.Top / yRatio), - Round(SourceRect.Right / xRatio), - Round(SourceRect.Bottom / yRatio)); - end - else - begin - // Calculates maximum crop selection - CalcMaxSelection(curCropArea); - end; - end; finally // Force Render Struct @@ -2584,13 +3301,14 @@ procedure TBGRAImageManipulation.tests; // Refresh; end; -function TBGRAImageManipulation.addCropArea(AArea: TRect; ARotate: double; AUserData: Integer): TCropArea; +function TBGRAImageManipulation.addCropArea(AArea: TRectF; AAreaUnit: TResolutionUnit; + AUserData: Integer): TCropArea; var newCropArea :TCropArea; begin try - newCropArea :=TCropArea.Create(Self, AArea, ARotate, AUserData); + newCropArea :=TCropArea.Create(Self, AArea, AAreaUnit, AUserData); newCropArea.BorderColor :=BGRAWhite; rCropAreas.add(newCropArea); @@ -2611,9 +3329,11 @@ function TBGRAImageManipulation.addCropArea(AArea: TRect; ARotate: double; AUser Invalidate; end; -function TBGRAImageManipulation.addScaledCropArea(AArea: TRect; ARotate: double; AUserData: Integer): TCropArea; +function TBGRAImageManipulation.addScaledCropArea(AArea: TRect; AUserData: Integer): TCropArea; begin - Result :=Self.addCropArea(Rect(0,0,0,0), ARotate, AUserData); + Result :=Self.addCropArea(RectF(0,0,0,0), rNewCropAreaDefault.rResolutionUnit, AUserData); + Result.rAspectRatio:=rNewCropAreaDefault.rAspectRatio; + Result.KeepAspectRatio:=rNewCropAreaDefault.rKeepAspectRatio; Result.ScaledArea :=AArea; if (fMouseCaught) @@ -2659,30 +3379,101 @@ procedure TBGRAImageManipulation.clearCropAreas; Invalidate; end; -procedure TBGRAImageManipulation.getAllResampledBitmaps(ACallBack: TgetAllBitmapsCallback); +procedure TBGRAImageManipulation.getAllResampledBitmaps(ACallBack: TgetAllBitmapsCallback; AUserData:Integer); var - i :Integer; + i :Integer; + curBitmap :TBGRABitmap; begin //Get Resampled Bitmap of each CropArea and pass it to CallBack for i:=0 to rCropAreas.Count-1 do - begin - ACallBack(rCropAreas[i].getResampledBitmap(getImageRect(fImageBitmap)), rCropAreas[i]); + try + curBitmap :=rCropAreas[i].getResampledBitmap; + ACallBack(curBitmap, rCropAreas[i], AUserData); + finally + if (curBitmap<>nil) + then curBitmap.Free; end; end; -procedure TBGRAImageManipulation.getAllBitmaps(ACallBack: TgetAllBitmapsCallback); +procedure TBGRAImageManipulation.getAllBitmaps(ACallBack: TgetAllBitmapsCallback; AUserData:Integer); var - i :Integer; + i :Integer; + curBitmap :TBGRABitmap; begin //Get Bitmap of each CropArea and pass it to CallBack + for i:=0 to rCropAreas.Count-1 do + try + curBitmap :=rCropAreas[i].getBitmap; + ACallBack(curBitmap, rCropAreas[i], AUserData); + finally + if (curBitmap<>nil) + then curBitmap.Free; + end; +end; + +procedure TBGRAImageManipulation.SetEmptyImageSizeToCropAreas(ReduceLarger: Boolean); +var + i :Integer; + curCropAreaRect :TRectF; + curCropArea :TCropArea; + mWidth, mHeight:Single; + xRatio, yRatio, resX :Single; + +begin + if Self.Empty and rEmptyImage.Allow and (rCropAreas.Count>0) then + begin + if ReduceLarger + then begin + mWidth:=0; + mHeight:=0; + end + else begin + mWidth:=EmptyImage.ResolutionWidth; + mHeight:=EmptyImage.ResolutionHeight; + if (mWidth=0) or (mHeight=0) then + begin + mWidth :=ResolutionUnitConvert(fImageBitmap.Width, ruNone, EmptyImage.ResolutionUnit, Self.PixelsPerInch); + mHeight :=ResolutionUnitConvert(fImageBitmap.Height, ruNone, EmptyImage.ResolutionUnit, Self.PixelsPerInch); + end; + end; + for i:=0 to rCropAreas.Count-1 do begin - ACallBack(rCropAreas[i].getBitmap, rCropAreas[i]); + curCropArea :=rCropAreas[i]; + curCropAreaRect :=curCropArea.Area; + + curCropAreaRect.Right :=ResolutionUnitConvert(curCropAreaRect.Right, curCropArea.rAreaUnit, + EmptyImage.ResolutionUnit, Self.PixelsPerInch); + curCropAreaRect.Bottom :=ResolutionUnitConvert(curCropAreaRect.Bottom, curCropArea.rAreaUnit, + EmptyImage.ResolutionUnit, Self.PixelsPerInch); + + if (curCropAreaRect.Right > mWidth) + then mWidth :=curCropAreaRect.Right; + if (curCropAreaRect.Bottom > mHeight) + then mHeight :=curCropAreaRect.Bottom; end; + + EmptyImage.ResolutionWidth :=mWidth; + EmptyImage.ResolutionHeight :=mHeight; + Resize; + end; +end; + +procedure TBGRAImageManipulation.SetEmptyImageSizeToNull; +begin + SetEmptyImageSize(ruPixelsPerInch, 0, 0); end; +procedure TBGRAImageManipulation.SetEmptyImageSize(AResolutionUnit: TResolutionUnit; AResolutionWidth, + AResolutionHeight: Single); +begin + EmptyImage.ResolutionUnit:=AResolutionUnit; + EmptyImage.rResolutionWidth:=AResolutionWidth; + EmptyImage.rResolutionHeight:=AResolutionHeight; + Resize; +end; procedure TBGRAImageManipulation.setBorderSize(const Value: byte); const @@ -2822,6 +3613,11 @@ procedure TBGRAImageManipulation.setAspectRatio(const Value: string); end; end; +procedure TBGRAImageManipulation.setEmptyImage(AValue: TBGRAEmptyImage); +begin + rEmptyImage.Assign(AValue); +end; + procedure TBGRAImageManipulation.setMinHeight(const Value: integer); begin if (Value <> fMinHeight) then @@ -2910,7 +3706,6 @@ procedure TBGRAImageManipulation.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: integer); var WorkRect: TRect; - overControl: boolean; ACursor :TCursor; begin @@ -2920,25 +3715,25 @@ procedure TBGRAImageManipulation.MouseDown(Button: TMouseButton; // Find the working area of the control WorkRect := getWorkRect; - // See if the mouse is inside the pressable part of the control - overControl := ((X >= WorkRect.Left) and (X <= WorkRect.Right) and - (Y >= WorkRect.Top) and (Y <= WorkRect.Bottom)); - // If over control - if ((overControl) and (Button = mbLeft) and (not (ssDouble in Shift))) then + if (((X >= WorkRect.Left) and (X <= WorkRect.Right) and + (Y >= WorkRect.Top) and (Y <= WorkRect.Bottom)) and + (Button = mbLeft) and (not (ssDouble in Shift))) then begin // If this was the left mouse button and nor double click fMouseCaught := True; fStartPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); + //rNewCropArea :=nil; SelectedCropArea :=Self.isOverAnchor(fStartPoint, fAnchorSelected, {%H-}ACursor); + if (SelectedCropArea<>nil) + then fStartArea :=SelectedCropArea.ScaledArea; if (fAnchorSelected = [NORTH, SOUTH, EAST, WEST]) then begin // Move the cropping area fStartPoint :=Point(X - SelectedCropArea.ScaledArea.Left, Y-SelectedCropArea.ScaledArea.Top); end else begin // Resize the cropping area from cornes - // Get the coordinate corresponding to the opposite quadrant and // set into fStartPoint if ((fAnchorSelected = [NORTH]) or (fAnchorSelected = [WEST]) or @@ -2965,219 +3760,213 @@ procedure TBGRAImageManipulation.MouseMove(Shift: TShiftState; X, Y: integer); newCoords: TCoord; Direction: TDirection; Bounds: TRect; - overControl: boolean; {%H-}overCropArea :TCropArea; ACursor :TCursor; -begin - // Call the inherited MouseMove() procedure - inherited MouseMove(Shift, X, Y); - - // Set default cursor - Cursor := crDefault; - - // Assume we don't need to repaint the control - needRepaint := False; + procedure newSelection; + begin + // Starts a new selection of cropping area + try + Cursor := crCross; + fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); - // Find the working area of the component - WorkRect := GetWorkRect; + // Copy coord + with newCoords do + begin + x1 := fStartPoint.X; + y1 := fStartPoint.Y; - // See if the mouse is inside the pressable part of the control - overControl := ((X >= WorkRect.Left) and (X <= WorkRect.Right) and - (Y >= WorkRect.Top) and (Y <= WorkRect.Bottom)); + x2 := fEndPoint.X; + y2 := fEndPoint.Y; + end; - // If image empty - if (fImageBitmap.Empty) then - exit; + // Determine direction + Direction := getDirection(fStartPoint, fEndPoint); - // If the mouse was originally clicked on the control - if (fMouseCaught) then - begin - // Determines limite values - Bounds := getImageRect(fResampledBitmap); + // Apply the ratio, if necessary + newCoords := ApplyRatioToAxes(newCoords, Direction, Bounds, rNewCropArea); - // If no anchor selected - if (fAnchorSelected = []) then - begin - // Starts a new selection of cropping area - try - Cursor := crCross; - fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); + // Determines minimum value on both axes + // new Area have KeepAspectRatio setted to bParent by default + newCoords := ApplyDimRestriction(newCoords, Direction, Bounds, fKeepAspectRatio); - // Copy coord - with newCoords do - begin - x1 := fStartPoint.X; - y1 := fStartPoint.Y; + if (rNewCropArea = Nil) + then begin + rNewCropArea :=addScaledCropArea(Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2)); + SelectedCropArea :=rNewCropArea; + end + else rNewCropArea.ScaledArea :=Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2); - x2 := fEndPoint.X; - y2 := fEndPoint.Y; - end; + finally + needRepaint := True; + end; + end; - // Determine direction - Direction := getDirection(fStartPoint, fEndPoint); + procedure moveCropping; + begin + Cursor := crSizeAll; - // Apply the ratio, if necessary - newCoords := ApplyRatioToAxes(newCoords, Direction, Bounds, rNewCropArea); + // Move the cropping area + try + WorkRect :=SelectedCropArea.ScaledArea; + WorkRect.Left :=fEndPoint.X-fStartPoint.X; //fStartPoint is Relative to CropArea + WorkRect.Top :=fEndPoint.Y-fStartPoint.Y; - // Determines minimum value on both axes - // new Area have KeepAspectRatio setted to bParent by default - newCoords := ApplyDimRestriction(newCoords, Direction, Bounds, fKeepAspectRatio); + //Out of Bounds check + if (WorkRect.Left<0) + then WorkRect.Left :=0; - if (rNewCropArea = Nil) - then begin - rNewCropArea :=addScaledCropArea(Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2)); - SelectedCropArea :=rNewCropArea; - end - else rNewCropArea.ScaledArea :=Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2); + if (WorkRect.Top<0) + then WorkRect.Top :=0; - finally - needRepaint := True; - end; - end - else - begin - // Get the actual point - fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); + if (WorkRect.Left+fStartArea.Width>Bounds.Right) + then WorkRect.Left :=Bounds.Right-fStartArea.Width; - // Check what the anchor was dragged - if (fAnchorSelected = [NORTH, SOUTH, EAST, WEST]) then - begin - Cursor := crSizeAll; + if (WorkRect.Top+fStartArea.Height>Bounds.Bottom) + then WorkRect.Top :=Bounds.Bottom-fStartArea.Height; - // Move the cropping area - try - WorkRect :=SelectedCropArea.ScaledArea; - newCoords.x1:=WorkRect.Width; - newCoords.y1:=WorkRect.Height; - WorkRect.Left :=fEndPoint.X-fStartPoint.X; //fStartPoint is Relative to CropArea - WorkRect.Top :=fEndPoint.Y-fStartPoint.Y; + WorkRect.Width :=fStartArea.Width; + WorkRect.Height:=fStartArea.Height; + SelectedCropArea.ScaledArea :=WorkRect; - //Out of Bounds check - if (WorkRect.Left<0) - then WorkRect.Left :=0; + finally + needRepaint := True; + end; + end; - if (WorkRect.Top<0) - then WorkRect.Top :=0; + procedure resizeCropping; + begin + // Resize the cropping area + try + if ((fAnchorSelected = [EAST]) or (fAnchorSelected = [WEST])) + then Cursor := crSizeWE + else if (NORTH in fAnchorSelected) + then begin + if (WEST in fAnchorSelected) + then Cursor := crSizeNW + else if (EAST in fAnchorSelected) + then Cursor := crSizeNE + else Cursor := crSizeNS; + end + else begin + if (WEST in fAnchorSelected) + then Cursor := crSizeSW + else if (EAST in fAnchorSelected) + then Cursor := crSizeSE + else Cursor := crSizeNS; + end; + + // Copy coord + with newCoords do + begin + x1 := fStartPoint.X; + y1 := fStartPoint.Y; - if (WorkRect.Left+newCoords.x1>Bounds.Right) - then WorkRect.Left :=Bounds.Right-newCoords.x1; + if (fAnchorSelected = [NORTH]) then + begin + x2 := fEndPoint.X - Abs(SelectedCropArea.ScaledArea.Right - SelectedCropArea.ScaledArea.Left) div 2; + y2 := fEndPoint.Y; + end + else + if (fAnchorSelected = [SOUTH]) then + begin + x2 := fEndPoint.X + Abs(SelectedCropArea.ScaledArea.Right - SelectedCropArea.ScaledArea.Left) div 2; + y2 := fEndPoint.Y; + end + else + if (fAnchorSelected = [EAST]) then + begin + x2 := fEndPoint.X; + y2 := fEndPoint.Y + Abs(SelectedCropArea.ScaledArea.Bottom - SelectedCropArea.ScaledArea.Top) div 2; + end + else + if (fAnchorSelected = [WEST]) then + begin + x2 := fEndPoint.X; + y2 := fEndPoint.Y - Abs(SelectedCropArea.ScaledArea.Bottom - SelectedCropArea.ScaledArea.Top) div 2; + end + else + begin + x2 := fEndPoint.X; + y2 := fEndPoint.Y; + end; + end; - if (WorkRect.Top+newCoords.y1>Bounds.Bottom) - then WorkRect.Top :=Bounds.Bottom-newCoords.y1; + // Determine direction + Direction := getDirection(fStartPoint, fEndPoint); - WorkRect.Width :=newCoords.x1; - WorkRect.Height:=newCoords.y1; - SelectedCropArea.ScaledArea :=WorkRect; + // Apply the ratio, if necessary + newCoords := ApplyRatioToAxes(newCoords, Direction, Bounds, SelectedCropArea); - finally - needRepaint := True; - end; - end - else - begin - // Resize the cropping area - try - if ((fAnchorSelected = [EAST]) or (fAnchorSelected = [WEST])) - then Cursor := crSizeWE - else if (NORTH in fAnchorSelected) - then begin - if (WEST in fAnchorSelected) - then Cursor := crSizeNW - else if (EAST in fAnchorSelected) - then Cursor := crSizeNE - else Cursor := crSizeNS; - end - else begin - if (WEST in fAnchorSelected) - then Cursor := crSizeSW - else if (EAST in fAnchorSelected) - then Cursor := crSizeSE - else Cursor := crSizeNS; - end; + // Determines minimum value on both axes + newCoords := ApplyDimRestriction(newCoords, Direction, Bounds, SelectedCropArea.getRealKeepAspectRatio); - // Copy coord - with newCoords do - begin - x1 := fStartPoint.X; - y1 := fStartPoint.Y; - - if (fAnchorSelected = [NORTH]) then - begin - x2 := fEndPoint.X - Abs(SelectedCropArea.ScaledArea.Right - SelectedCropArea.ScaledArea.Left) div 2; - y2 := fEndPoint.Y; - end - else - if (fAnchorSelected = [SOUTH]) then - begin - x2 := fEndPoint.X + Abs(SelectedCropArea.ScaledArea.Right - SelectedCropArea.ScaledArea.Left) div 2; - y2 := fEndPoint.Y; - end - else - if (fAnchorSelected = [EAST]) then - begin - x2 := fEndPoint.X; - y2 := fEndPoint.Y + Abs(SelectedCropArea.ScaledArea.Bottom - SelectedCropArea.ScaledArea.Top) div 2; - end - else - if (fAnchorSelected = [WEST]) then - begin - x2 := fEndPoint.X; - y2 := fEndPoint.Y - Abs(SelectedCropArea.ScaledArea.Bottom - SelectedCropArea.ScaledArea.Top) div 2; - end - else - begin - x2 := fEndPoint.X; - y2 := fEndPoint.Y; - end; - end; + SelectedCropArea.ScaledArea := Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2); + finally + needRepaint := True; + end; + end; - // Determine direction - Direction := getDirection(fStartPoint, fEndPoint); +begin + // Call the inherited MouseMove() procedure + inherited MouseMove(Shift, X, Y); - // Apply the ratio, if necessary - newCoords := ApplyRatioToAxes(newCoords, Direction, Bounds, SelectedCropArea); + // Set default cursor + Cursor := crDefault; - // Determines minimum value on both axes - newCoords := ApplyDimRestriction(newCoords, Direction, Bounds, SelectedCropArea.getRealKeepAspectRatio); + // Find the working area of the component + WorkRect := GetWorkRect; - SelectedCropArea.ScaledArea := Rect(newCoords.x1, newCoords.y1, newCoords.x2, newCoords.y2); - finally - needRepaint := True; - end; - end; - end; - end - else - begin - // If the mouse is just moving over the control, and wasn't originally click - // in the control - if (overControl) then - begin - // Mouse is inside the pressable part of the control - Cursor := crCross; - fAnchorSelected := []; - fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); - - // Verifies that is positioned on an anchor - ACursor := crDefault; - overCropArea :=Self.isOverAnchor(fEndPoint, fAnchorSelected, ACursor); - Cursor :=ACursor; - end; - end; + // If the mouse was originally clicked on the control + if fMouseCaught + then begin + // Assume we don't need to repaint the control + needRepaint := False; + + // Determines limite values + Bounds := getImageRect(fResampledBitmap); + + // If no anchor selected + if (fAnchorSelected = []) + then newSelection + else begin + // Get the actual point + fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); + + // Check what the anchor was dragged + if (fAnchorSelected = [NORTH, SOUTH, EAST, WEST]) + then moveCropping + else resizeCropping; + end; - // If we need to repaint - if needRepaint then - begin - //SelectedCropArea.ScaledArea :=curCropAreaRect; - SelectedCropArea.CalculateAreaFromScaledArea; - if assigned(rOnCropAreaChanged) - then rOnCropAreaChanged(Self, SelectedCropArea); + // If we need to repaint + if needRepaint then + begin + SelectedCropArea.CalculateAreaFromScaledArea; + if assigned(rOnCropAreaChanged) + then rOnCropAreaChanged(Self, SelectedCropArea); - // Invalidate the control for repainting - Render; - Refresh; - end; + // Invalidate the control for repainting + Render; + Refresh; + end; + end + else begin + // If the mouse is just moving over the control, and wasn't originally click in the control + if ((X >= WorkRect.Left) and (X <= WorkRect.Right) and + (Y >= WorkRect.Top) and (Y <= WorkRect.Bottom)) then + begin + // Mouse is inside the pressable part of the control + Cursor := crCross; + fAnchorSelected := []; + fEndPoint := Point(X - WorkRect.Left, Y - WorkRect.Top); + + // Verifies that is positioned on an anchor + ACursor := crDefault; + overCropArea :=Self.isOverAnchor(fEndPoint, fAnchorSelected, ACursor); + Cursor :=ACursor; + end; + end; end; procedure TBGRAImageManipulation.MouseUp(Button: TMouseButton; @@ -3191,68 +3980,83 @@ procedure TBGRAImageManipulation.MouseUp(Button: TMouseButton; // Call the inherited MouseUp() procedure inherited MouseUp(Button, Shift, X, Y); - // Assume we don't need to repaint the control - needRepaint := False; - // If the mouse was originally clicked over the control if (fMouseCaught) then begin // Show that the mouse is no longer caught fMouseCaught := False; - // Check what the anchor was dragged - if (fAnchorSelected = [NORTH, SOUTH, EAST, WEST]) then - begin - // Move the cropping area - try - finally - needRepaint := True; - end; - end - else - begin - // Ends a new selection of cropping area - if (rNewCropArea <> Nil) then - begin - SelectedCropArea :=rNewCropArea; - rNewCropArea :=Nil; - curCropAreaRect :=SelectedCropArea.ScaledArea; + // Assume we don't need to repaint the control + needRepaint := False; - if (curCropAreaRect.Left > curCropAreaRect.Right) then - begin - // Swap left and right coordinates - temp := curCropAreaRect.Left; - curCropAreaRect.Left := curCropAreaRect.Right; - curCropAreaRect.Right := temp; - end; + if (rNewCropArea = Nil) + then begin + if (ssAlt in Shift) + then begin + SelectedCropArea.ScaledArea :=fStartArea; + needRepaint :=True; + end + end + else begin // Ends a new selection of cropping area + if (ssAlt in Shift) + then begin + delCropArea(rNewCropArea); + rNewCropArea :=Nil; + needRepaint :=False; + end + else begin + SelectedCropArea :=rNewCropArea; + rNewCropArea :=Nil; + curCropAreaRect :=SelectedCropArea.ScaledArea; + + if (curCropAreaRect.Left > curCropAreaRect.Right) then + begin + // Swap left and right coordinates + temp := curCropAreaRect.Left; + curCropAreaRect.Left := curCropAreaRect.Right; + curCropAreaRect.Right := temp; + end; + + if (curCropAreaRect.Top > curCropAreaRect.Bottom) then + begin + // Swap Top and Bottom coordinates + temp := curCropAreaRect.Top; + curCropAreaRect.Top := curCropAreaRect.Bottom; + curCropAreaRect.Bottom := temp; + end; + needRepaint :=True; + end; + end; - if (curCropAreaRect.Top > curCropAreaRect.Bottom) then - begin - // Swap Top and Bottom coordinates - temp := curCropAreaRect.Top; - curCropAreaRect.Top := curCropAreaRect.Bottom; - curCropAreaRect.Bottom := temp; - end; + fAnchorSelected := []; - needRepaint := True; - end; - end; + // If we need to repaint + if needRepaint then + begin + SelectedCropArea.CalculateAreaFromScaledArea; + if assigned(rOnCropAreaChanged) + then rOnCropAreaChanged(Self, SelectedCropArea); - fAnchorSelected := []; + // Invalidate the control for repainting + Render; + Refresh; + end; end; + end; - // If we need to repaint - if needRepaint then - begin - SelectedCropArea.CalculateAreaFromScaledArea; - if assigned(rOnCropAreaChanged) - then rOnCropAreaChanged(Self, SelectedCropArea); +procedure TBGRAImageManipulation.DoContextPopup(MousePos: TPoint; var Handled: Boolean); +var + xAnchorSelected :TDirection; + xCursor :TCursor; + mouseCropArea:TCropArea; - // Invalidate the control for repainting - Render; - Refresh; +begin + if Assigned(rOnContextPopup) then + begin + mouseCropArea :=Self.isOverAnchor(MousePos, xAnchorSelected, {%H-}xCursor); + rOnContextPopup(Self, mouseCropArea, xAnchorSelected, MousePos, Handled); end; - end; +end; { ============================================================================ } diff --git a/bgraknob.pas b/bgraknob.pas index a93caa2..f0e979b 100644 --- a/bgraknob.pas +++ b/bgraknob.pas @@ -160,7 +160,7 @@ procedure TBGRAKnob.CreateKnobBmp; v.x := v.x /(tx / 2 + 1); v.y := v.y / (ty / 2 + 1); //compute squared distance with scalar product - d2 := v ** v; + d2 := v {$if FPC_FULLVERSION < 030301}*{$ELSE}**{$ENDIF} v; //interpolate as quadratic curve and apply power function if d2 > 1 then h := 0 diff --git a/bgravirtualscreen.pas b/bgravirtualscreen.pas index 480b796..50c2e20 100644 --- a/bgravirtualscreen.pas +++ b/bgravirtualscreen.pas @@ -61,11 +61,13 @@ TCustomBGRAVirtualScreen = class(TBGRACustomPanel) public { Public declarations } constructor Create(TheOwner: TComponent); override; + function BitmapRectToClient(ARect: TRect): TRect; procedure RedrawBitmap; overload; procedure RedrawBitmap(ARect: TRect); overload; procedure RedrawBitmap(ARectArray: array of TRect); overload; procedure DiscardBitmap; overload; procedure DiscardBitmap(ARect: TRect); overload; + procedure InvalidateBitmap(ARect: TRect); destructor Destroy; override; public property OnRedraw: TBGRARedrawEvent Read FOnRedraw Write FOnRedraw; @@ -379,6 +381,15 @@ constructor TCustomBGRAVirtualScreen.Create(TheOwner: TComponent); Color := clWhite; end; +function TCustomBGRAVirtualScreen.BitmapRectToClient(ARect: TRect): TRect; +var + scale: Double; +begin + scale := BitmapScale; + result := rect(floor(ARect.Left/scale), floor(ARect.Top/scale), + ceil(ARect.Right/scale), ceil(ARect.Bottom/scale)); +end; + procedure TCustomBGRAVirtualScreen.RedrawBitmap; begin RedrawBitmapContent; @@ -389,7 +400,6 @@ procedure TCustomBGRAVirtualScreen.RedrawBitmap; procedure TCustomBGRAVirtualScreen.RedrawBitmap(ARect: TRect); var All, displayRect: TRect; - scale: Double; begin if Assigned(FBGRA) then begin @@ -413,9 +423,7 @@ procedure TCustomBGRAVirtualScreen.RedrawBitmap(ARect: TRect); FBGRA.ClipRect := ARect; RedrawBitmapContent; FBGRA.NoClip; - scale := BitmapScale; - displayRect := rect(round(ARect.Left/scale), round(ARect.Top/scale), - round(ARect.Right/scale), round(ARect.Bottom/scale)); + displayRect := BitmapRectToClient(ARect); {$IFDEF LINUX} FBGRA.DrawPart(ARect, Canvas, displayRect, True); {$ELSE} @@ -533,7 +541,6 @@ procedure TCustomBGRAVirtualScreen.DiscardBitmap; procedure TCustomBGRAVirtualScreen.DiscardBitmap(ARect: TRect); var - scale: Double; displayRect: TRect; begin ARect.Intersect(rect(0,0,FBGRA.Width,FBGRA.Height)); @@ -544,13 +551,19 @@ procedure TCustomBGRAVirtualScreen.DiscardBitmap(ARect: TRect); FDiscardedRect := ARect else FDiscardedRect.Union(ARect); - scale := BitmapScale; - displayRect := rect(round(ARect.Left/scale), round(ARect.Top/scale), - round(ARect.Right/scale), round(ARect.Bottom/scale)); + displayRect := BitmapRectToClient(ARect); InvalidateRect(self.Handle, @displayRect, false); end; end; +procedure TCustomBGRAVirtualScreen.InvalidateBitmap(ARect: TRect); +var + displayRect: TRect; +begin + displayRect := BitmapRectToClient(ARect); + InvalidateRect(self.Handle, @displayRect, false); +end; + destructor TCustomBGRAVirtualScreen.Destroy; begin FBGRA.Free; diff --git a/styles/windows11-panel-light.bcpnl b/styles/windows11-panel-light.bcpnl new file mode 100644 index 0000000..049d2eb --- /dev/null +++ b/styles/windows11-panel-light.bcpnl @@ -0,0 +1,115 @@ +[HEADER] +Author=Me +Description= +ControlClass=TBCPanel + +[PROPERTIES] +Align = alNone +AnchorSideBottom.Side = asrTop +AnchorSideLeft.Side = asrTop +AnchorSideRight.Side = asrTop +AnchorSideTop.Side = asrTop +Anchors = akTop,akLeft,akRight +AutoSize = 0 +Background.Color = 16514043 +Background.ColorOpacity = 255 +Background.Gradient1.ColorCorrection = 1 +Background.Gradient1.DrawMode = dmSet +Background.Gradient1.EndColor = 0 +Background.Gradient1.EndColorOpacity = 255 +Background.Gradient1.GradientType = gtLinear +Background.Gradient1.Point1XPercent = 0 +Background.Gradient1.Point1YPercent = 0 +Background.Gradient1.Point2XPercent = 0 +Background.Gradient1.Point2YPercent = 100 +Background.Gradient1.Sinus = 0 +Background.Gradient1.StartColor = 16777215 +Background.Gradient1.StartColorOpacity = 255 +Background.Gradient1EndPercent = 35 +Background.Gradient2.ColorCorrection = 1 +Background.Gradient2.DrawMode = dmSet +Background.Gradient2.EndColor = 0 +Background.Gradient2.EndColorOpacity = 255 +Background.Gradient2.GradientType = gtLinear +Background.Gradient2.Point1XPercent = 0 +Background.Gradient2.Point1YPercent = 0 +Background.Gradient2.Point2XPercent = 0 +Background.Gradient2.Point2YPercent = 100 +Background.Gradient2.Sinus = 0 +Background.Gradient2.StartColor = 16777215 +Background.Gradient2.StartColorOpacity = 255 +Background.Style = bbsColor +BevelInner = bvNone +BevelOuter = bvNone +BevelWidth = 1 +Border.Color = 15066597 +Border.ColorOpacity = 255 +Border.LightColor = 16777215 +Border.LightOpacity = 255 +Border.LightWidth = 0 +Border.Style = bboSolid +Border.Width = 1 +BorderBCStyle = bpsBorder +BorderSpacing.Around = 0 +BorderSpacing.Bottom = 0 +BorderSpacing.CellAlignHorizontal = ccaFill +BorderSpacing.CellAlignVertical = ccaFill +BorderSpacing.InnerBorder = 0 +BorderSpacing.Left = 0 +BorderSpacing.Right = 0 +BorderSpacing.Top = 0 +ChildSizing.ControlsPerLine = 0 +ChildSizing.EnlargeHorizontal = crsAnchorAligning +ChildSizing.EnlargeVertical = crsAnchorAligning +ChildSizing.HorizontalSpacing = 0 +ChildSizing.Layout = cclNone +ChildSizing.LeftRightSpacing = 0 +ChildSizing.ShrinkHorizontal = crsAnchorAligning +ChildSizing.ShrinkVertical = crsAnchorAligning +ChildSizing.TopBottomSpacing = 0 +ChildSizing.VerticalSpacing = 0 +Color = 15987699 +Constraints.MaxHeight = 0 +Constraints.MaxWidth = 0 +Constraints.MinHeight = 0 +Constraints.MinWidth = 0 +Cursor = 0 +DockSite = 0 +DragCursor = -12 +DragKind = dkDrag +DragMode = dmManual +Enabled = 1 +FontEx.Color = 536870912 +FontEx.DisabledColor = 536870911 +FontEx.EndEllipsis = 0 +FontEx.FontQuality = fqSystemClearType +FontEx.Height = 0 +FontEx.Name = default +FontEx.PaddingBottom = 0 +FontEx.PaddingLeft = 0 +FontEx.PaddingRight = 0 +FontEx.PaddingTop = 0 +FontEx.Shadow = 0 +FontEx.ShadowColor = 0 +FontEx.ShadowColorOpacity = 255 +FontEx.ShadowOffsetX = 5 +FontEx.ShadowOffsetY = 5 +FontEx.ShadowRadius = 5 +FontEx.SingleLine = 1 +FontEx.Style = +FontEx.TextAlignment = bcaCenter +FontEx.WordBreak = 0 +HelpContext = 0 +HelpKeyword = +HelpType = htContext +Hint = +ParentBackground = 0 +Rounding.RoundOptions = +Rounding.RoundX = 5 +Rounding.RoundY = 5 +ShowHint = 0 +TabOrder = 0 +TabStop = 0 +Tag = 0 +UseDockManager = 1 +Visible = 1 diff --git a/styles/windows11-panel-text-light.bclbl b/styles/windows11-panel-text-light.bclbl new file mode 100644 index 0000000..b4cea3f --- /dev/null +++ b/styles/windows11-panel-text-light.bclbl @@ -0,0 +1,89 @@ +[HEADER] +Author=Me +Description= +ControlClass=TBCLabel + +[PROPERTIES] +Align = alNone +AnchorSideBottom.Side = asrTop +AnchorSideLeft.Side = asrTop +AnchorSideRight.Side = asrTop +AnchorSideTop.Side = asrTop +Anchors = akTop,akLeft +AutoSize = 1 +Background.Color = 0 +Background.ColorOpacity = 255 +Background.Gradient1.ColorCorrection = 1 +Background.Gradient1.DrawMode = dmSet +Background.Gradient1.EndColor = 0 +Background.Gradient1.EndColorOpacity = 255 +Background.Gradient1.GradientType = gtLinear +Background.Gradient1.Point1XPercent = 0 +Background.Gradient1.Point1YPercent = 0 +Background.Gradient1.Point2XPercent = 0 +Background.Gradient1.Point2YPercent = 100 +Background.Gradient1.Sinus = 0 +Background.Gradient1.StartColor = 16777215 +Background.Gradient1.StartColorOpacity = 255 +Background.Gradient1EndPercent = 35 +Background.Gradient2.ColorCorrection = 1 +Background.Gradient2.DrawMode = dmSet +Background.Gradient2.EndColor = 0 +Background.Gradient2.EndColorOpacity = 255 +Background.Gradient2.GradientType = gtLinear +Background.Gradient2.Point1XPercent = 0 +Background.Gradient2.Point1YPercent = 0 +Background.Gradient2.Point2XPercent = 0 +Background.Gradient2.Point2YPercent = 100 +Background.Gradient2.Sinus = 0 +Background.Gradient2.StartColor = 16777215 +Background.Gradient2.StartColorOpacity = 255 +Background.Style = bbsClear +Border.Color = 0 +Border.ColorOpacity = 255 +Border.LightColor = 16777215 +Border.LightOpacity = 255 +Border.LightWidth = 0 +Border.Style = bboNone +Border.Width = 1 +BorderSpacing.Around = 0 +BorderSpacing.Bottom = 0 +BorderSpacing.CellAlignHorizontal = ccaFill +BorderSpacing.CellAlignVertical = ccaFill +BorderSpacing.InnerBorder = 0 +BorderSpacing.Left = 0 +BorderSpacing.Right = 0 +BorderSpacing.Top = 0 +Cursor = 0 +Enabled = 1 +FontEx.Color = 6250335 +FontEx.DisabledColor = 536870911 +FontEx.EndEllipsis = 0 +FontEx.FontQuality = fqSystemClearType +FontEx.Height = 14 +FontEx.Name = default +FontEx.PaddingBottom = 0 +FontEx.PaddingLeft = 0 +FontEx.PaddingRight = 0 +FontEx.PaddingTop = 0 +FontEx.Shadow = 0 +FontEx.ShadowColor = 0 +FontEx.ShadowColorOpacity = 255 +FontEx.ShadowOffsetX = 5 +FontEx.ShadowOffsetY = 5 +FontEx.ShadowRadius = 5 +FontEx.SingleLine = 1 +FontEx.Style = +FontEx.TextAlignment = bcaCenter +FontEx.WordBreak = 0 +HelpContext = 0 +HelpKeyword = +HelpType = htContext +Hint = +InnerMargin = 0 +Rounding.RoundOptions = +Rounding.RoundX = 1 +Rounding.RoundY = 1 +ShowHint = 0 +Tag = 0 +Visible = 1 diff --git a/styles/windows11-panel-title-light.bclbl b/styles/windows11-panel-title-light.bclbl new file mode 100644 index 0000000..4034170 --- /dev/null +++ b/styles/windows11-panel-title-light.bclbl @@ -0,0 +1,89 @@ +[HEADER] +Author=Me +Description= +ControlClass=TBCLabel + +[PROPERTIES] +Align = alNone +AnchorSideBottom.Side = asrTop +AnchorSideLeft.Side = asrTop +AnchorSideRight.Side = asrTop +AnchorSideTop.Side = asrTop +Anchors = akTop,akLeft +AutoSize = 1 +Background.Color = 0 +Background.ColorOpacity = 255 +Background.Gradient1.ColorCorrection = 1 +Background.Gradient1.DrawMode = dmSet +Background.Gradient1.EndColor = 0 +Background.Gradient1.EndColorOpacity = 255 +Background.Gradient1.GradientType = gtLinear +Background.Gradient1.Point1XPercent = 0 +Background.Gradient1.Point1YPercent = 0 +Background.Gradient1.Point2XPercent = 0 +Background.Gradient1.Point2YPercent = 100 +Background.Gradient1.Sinus = 0 +Background.Gradient1.StartColor = 16777215 +Background.Gradient1.StartColorOpacity = 255 +Background.Gradient1EndPercent = 35 +Background.Gradient2.ColorCorrection = 1 +Background.Gradient2.DrawMode = dmSet +Background.Gradient2.EndColor = 0 +Background.Gradient2.EndColorOpacity = 255 +Background.Gradient2.GradientType = gtLinear +Background.Gradient2.Point1XPercent = 0 +Background.Gradient2.Point1YPercent = 0 +Background.Gradient2.Point2XPercent = 0 +Background.Gradient2.Point2YPercent = 100 +Background.Gradient2.Sinus = 0 +Background.Gradient2.StartColor = 16777215 +Background.Gradient2.StartColorOpacity = 255 +Background.Style = bbsClear +Border.Color = 0 +Border.ColorOpacity = 255 +Border.LightColor = 16777215 +Border.LightOpacity = 255 +Border.LightWidth = 0 +Border.Style = bboNone +Border.Width = 1 +BorderSpacing.Around = 0 +BorderSpacing.Bottom = 0 +BorderSpacing.CellAlignHorizontal = ccaFill +BorderSpacing.CellAlignVertical = ccaFill +BorderSpacing.InnerBorder = 0 +BorderSpacing.Left = 0 +BorderSpacing.Right = 0 +BorderSpacing.Top = 0 +Cursor = 0 +Enabled = 1 +FontEx.Color = 1776411 +FontEx.DisabledColor = 536870911 +FontEx.EndEllipsis = 0 +FontEx.FontQuality = fqSystemClearType +FontEx.Height = 20 +FontEx.Name = default +FontEx.PaddingBottom = 0 +FontEx.PaddingLeft = 0 +FontEx.PaddingRight = 0 +FontEx.PaddingTop = 0 +FontEx.Shadow = 0 +FontEx.ShadowColor = 0 +FontEx.ShadowColorOpacity = 255 +FontEx.ShadowOffsetX = 5 +FontEx.ShadowOffsetY = 5 +FontEx.ShadowRadius = 5 +FontEx.SingleLine = 1 +FontEx.Style = fsBold +FontEx.TextAlignment = bcaCenter +FontEx.WordBreak = 0 +HelpContext = 0 +HelpKeyword = +HelpType = htContext +Hint = +InnerMargin = 0 +Rounding.RoundOptions = +Rounding.RoundX = 1 +Rounding.RoundY = 1 +ShowHint = 0 +Tag = 0 +Visible = 1 diff --git a/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpi b/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpi index a32824a..6c1da25 100644 --- a/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpi +++ b/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpi @@ -7,6 +7,7 @@ + diff --git a/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpr b/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpr index 9fcf8e6..2dccb76 100644 --- a/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpr +++ b/test/test_bgraimagemanipulation/ProjectBGRAImageManipulationDemo.lpr @@ -12,6 +12,8 @@ {$R *.res} begin + Application.Scaled:=True; + Application.Title:=''; Application.Initialize; Application.CreateForm(TFormBGRAImageManipulationDemo, FormBGRAImageManipulationDemo); Application.Run; diff --git a/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.lfm b/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.lfm index 34deeeb..b17d534 100644 --- a/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.lfm +++ b/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.lfm @@ -1,20 +1,20 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo - Left = 417 - Height = 460 - Top = 136 - Width = 847 + Left = 262 + Height = 513 + Top = 125 + Width = 926 Caption = 'Demonstration of TBGRAImageManipulation' - ClientHeight = 460 - ClientWidth = 847 + ClientHeight = 513 + ClientWidth = 926 OnCloseQuery = FormCloseQuery OnCreate = FormCreate ShowHint = True - LCLVersion = '2.2.6.0' + LCLVersion = '3.99.0.0' object Background: TBCPanel - Left = 627 - Height = 460 + Left = 678 + Height = 513 Top = 0 - Width = 220 + Width = 248 Align = alRight Background.Color = clSilver Background.Gradient1.StartColor = clWhite @@ -49,19 +49,19 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Rounding.RoundY = 1 TabOrder = 0 object RateCompression: TTrackBar - Left = 20 - Height = 45 - Top = 227 + Left = 40 + Height = 24 + Top = 336 Width = 180 Max = 100 Position = 80 TabOrder = 0 end object KeepAspectRatio: TCheckBox - Left = 20 + Left = 25 Height = 19 - Top = 104 - Width = 117 + Top = 176 + Width = 115 Caption = 'Keep aspect ratio' Checked = True Color = clWhite @@ -87,28 +87,28 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Transparent = False end object lbCompression: TLabel - Left = 20 + Left = 25 Height = 15 - Top = 208 - Width = 113 - Caption = 'Compression adjust :' + Top = 320 + Width = 77 + Caption = 'Compression :' Font.Color = clWhite Font.Style = [fsBold] ParentColor = False ParentFont = False end object edAspectRatio: TEdit - Left = 118 + Left = 123 Height = 23 - Top = 132 + Top = 204 Width = 44 TabOrder = 2 Text = '3:4' end object lbAspectRatio: TLabel - Left = 20 + Left = 25 Height = 15 - Top = 136 + Top = 208 Width = 76 Caption = 'Aspect Ratio :' Color = clBlack @@ -122,7 +122,7 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Left = 10 Height = 40 Top = 8 - Width = 200 + Width = 134 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 StateClicked.Background.Gradient1.GradientType = gtRadial @@ -286,9 +286,9 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnSavePicture: TBCButton - Left = 10 + Left = 15 Height = 40 - Top = 368 + Top = 440 Width = 200 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -453,10 +453,10 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnSetAspectRatio: TBCButton - Left = 170 + Left = 175 Height = 28 Hint = 'Apply new aspect ratio' - Top = 132 + Top = 204 Width = 40 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -620,10 +620,10 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnGetAspectRatioFromImage: TBCButton - Left = 20 + Left = 25 Height = 30 Hint = 'Get aspect ratio from image' - Top = 168 + Top = 240 Width = 30 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -787,10 +787,10 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnRotateLeft: TBCButton - Left = 64 + Left = 69 Height = 30 Hint = 'Rotate Left' - Top = 168 + Top = 240 Width = 30 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -954,10 +954,10 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnRotateRight: TBCButton - Left = 100 + Left = 105 Height = 30 Hint = 'Rotate Right' - Top = 168 + Top = 240 Width = 30 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -1121,9 +1121,9 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnShape: TBCButton - Left = 10 - Height = 48 - Top = 224 + Left = 32 + Height = 24 + Top = 336 Width = 200 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -1211,9 +1211,9 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object btnSavePictureAll: TBCButton - Left = 10 + Left = 15 Height = 40 - Top = 320 + Top = 392 Width = 200 StateClicked.Background.Gradient1.StartColor = 8404992 StateClicked.Background.Gradient1.EndColor = 4194304 @@ -1378,26 +1378,246 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo MemoryUsage = bmuHigh end object chkFullSize: TCheckBox - Left = 24 + Left = 45 Height = 19 - Top = 288 - Width = 152 + Top = 368 + Width = 150 Caption = 'Save Original Size picture' Checked = True State = cbChecked TabOrder = 3 end + object lbResolution: TLabel + Left = 24 + Height = 15 + Top = 95 + Width = 65 + Caption = 'Resolution : ' + end + object BCLabel7: TBCLabel + Left = 11 + Height = 15 + Top = 296 + Width = 44 + Background.Gradient1.StartColor = clWhite + Background.Gradient1.EndColor = clBlack + Background.Gradient1.GradientType = gtLinear + Background.Gradient1.Point1XPercent = 0 + Background.Gradient1.Point1YPercent = 0 + Background.Gradient1.Point2XPercent = 0 + Background.Gradient1.Point2YPercent = 100 + Background.Gradient2.StartColor = clWhite + Background.Gradient2.EndColor = clBlack + Background.Gradient2.GradientType = gtLinear + Background.Gradient2.Point1XPercent = 0 + Background.Gradient2.Point1YPercent = 0 + Background.Gradient2.Point2XPercent = 0 + Background.Gradient2.Point2YPercent = 100 + Background.Gradient1EndPercent = 35 + Background.Style = bbsClear + Border.Style = bboNone + Caption = 'Format :' + FontEx.Color = clDefault + FontEx.FontQuality = fqSystemClearType + FontEx.Shadow = False + FontEx.ShadowRadius = 5 + FontEx.ShadowOffsetX = 5 + FontEx.ShadowOffsetY = 5 + FontEx.Style = [] + Rounding.RoundX = 1 + Rounding.RoundY = 1 + end + object cbSaveFormat: TComboBox + Left = 60 + Height = 23 + Top = 288 + Width = 180 + ItemHeight = 15 + Style = csDropDownList + TabOrder = 4 + end + object SpeedButton1: TSpeedButton + Left = 208 + Height = 19 + Top = 56 + Width = 32 + AutoSize = True + Caption = ':Tests' + OnClick = SpeedButton1Click + end + object btnEmptyImage: TBCButton + Left = 152 + Height = 40 + Hint = 'Get aspect ratio from image' + Top = 8 + Width = 88 + StateClicked.Background.Gradient1.StartColor = 8404992 + StateClicked.Background.Gradient1.EndColor = 4194304 + StateClicked.Background.Gradient1.GradientType = gtRadial + StateClicked.Background.Gradient1.Point1XPercent = 50 + StateClicked.Background.Gradient1.Point1YPercent = 100 + StateClicked.Background.Gradient1.Point2XPercent = 0 + StateClicked.Background.Gradient1.Point2YPercent = 0 + StateClicked.Background.Gradient2.StartColor = clWhite + StateClicked.Background.Gradient2.EndColor = clBlack + StateClicked.Background.Gradient2.GradientType = gtLinear + StateClicked.Background.Gradient2.Point1XPercent = 0 + StateClicked.Background.Gradient2.Point1YPercent = 0 + StateClicked.Background.Gradient2.Point2XPercent = 0 + StateClicked.Background.Gradient2.Point2YPercent = 100 + StateClicked.Background.Gradient1EndPercent = 100 + StateClicked.Background.Style = bbsGradient + StateClicked.Border.Style = bboNone + StateClicked.FontEx.Color = 16770790 + StateClicked.FontEx.FontQuality = fqSystemClearType + StateClicked.FontEx.Shadow = True + StateClicked.FontEx.ShadowRadius = 2 + StateClicked.FontEx.ShadowOffsetX = 1 + StateClicked.FontEx.ShadowOffsetY = 1 + StateClicked.FontEx.Style = [fsBold] + StateHover.Background.Gradient1.StartColor = 16744448 + StateHover.Background.Gradient1.EndColor = 8404992 + StateHover.Background.Gradient1.GradientType = gtRadial + StateHover.Background.Gradient1.Point1XPercent = 50 + StateHover.Background.Gradient1.Point1YPercent = 100 + StateHover.Background.Gradient1.Point2XPercent = 0 + StateHover.Background.Gradient1.Point2YPercent = 0 + StateHover.Background.Gradient2.StartColor = clWhite + StateHover.Background.Gradient2.EndColor = clBlack + StateHover.Background.Gradient2.GradientType = gtLinear + StateHover.Background.Gradient2.Point1XPercent = 0 + StateHover.Background.Gradient2.Point1YPercent = 0 + StateHover.Background.Gradient2.Point2XPercent = 0 + StateHover.Background.Gradient2.Point2YPercent = 100 + StateHover.Background.Gradient1EndPercent = 100 + StateHover.Background.Style = bbsGradient + StateHover.Border.Style = bboNone + StateHover.FontEx.Color = clWhite + StateHover.FontEx.FontQuality = fqSystemClearType + StateHover.FontEx.Shadow = True + StateHover.FontEx.ShadowRadius = 2 + StateHover.FontEx.ShadowOffsetX = 1 + StateHover.FontEx.ShadowOffsetY = 1 + StateHover.FontEx.Style = [fsBold] + StateNormal.Background.Gradient1.StartColor = 4194304 + StateNormal.Background.Gradient1.EndColor = 8405056 + StateNormal.Background.Gradient1.GradientType = gtLinear + StateNormal.Background.Gradient1.Point1XPercent = 0 + StateNormal.Background.Gradient1.Point1YPercent = 0 + StateNormal.Background.Gradient1.Point2XPercent = 0 + StateNormal.Background.Gradient1.Point2YPercent = 100 + StateNormal.Background.Gradient2.StartColor = 8405056 + StateNormal.Background.Gradient2.EndColor = 4194304 + StateNormal.Background.Gradient2.GradientType = gtRadial + StateNormal.Background.Gradient2.Point1XPercent = 50 + StateNormal.Background.Gradient2.Point1YPercent = 100 + StateNormal.Background.Gradient2.Point2XPercent = 0 + StateNormal.Background.Gradient2.Point2YPercent = 0 + StateNormal.Background.Gradient1EndPercent = 60 + StateNormal.Background.Style = bbsGradient + StateNormal.Border.Style = bboNone + StateNormal.FontEx.Color = 16770790 + StateNormal.FontEx.FontQuality = fqSystemClearType + StateNormal.FontEx.Shadow = True + StateNormal.FontEx.ShadowRadius = 2 + StateNormal.FontEx.ShadowOffsetX = 1 + StateNormal.FontEx.ShadowOffsetY = 1 + StateNormal.FontEx.Style = [fsBold] + Caption = 'Empty' + Color = clNone + DropDownWidth = 16 + DropDownArrowSize = 8 + GlobalOpacity = 255 + Glyph.Data = { + C6070000424DC607000000000000360000002800000016000000160000000100 + 2000000000009007000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0064646466D4D4 + D4DAD6D6D6DCD8D8D8DCD8D8D8DCD8D8D8DCD8D8D8DCD8D8D8DCD9D9D9DCD9D9 + D9DCD4D3D1DCABA9A4BD0F0F0F11FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0087878779F7F7F7FFF8F8F8FFFAFA + FAFFFAFAFAFFFBFBFBFFFCFCFCFFFDFDFDFFFEFEFEFFFFFFFFFFF7F7F7FFDCDB + DAFFBBBAB5E625252515FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0087878779F7F7F7FFF8F8F8FFFAFAFAFFFAFAFAFFFBFB + FBFFFCFCFCFFFDFDFDFFFEFEFEFFFEFEFEFFF9F9F9FFE2E2E2FFD8D8D7FFBDBD + B9F23D463D1DFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0087878779F7F7F6FFF7F7F7FFF9F9F9FFFAFAFAFFFBFBFBFFFCFCFCFFFDFD + FDFFFDFDFDFFFEFEFEFFFBFBFBFFEEEEEEFFCCCBCBFFF9FAFAFFBEBFBBF53030 + 301AFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0087878779F6F6 + F6FFF7F7F7FFF9F9F9FFFAFAFAFFFBFBFBFFFCFCFCFFFCFCFCFFFDFDFDFFFEFE + FEFFFEFEFEFFF7F7F7FFDCDCDCFFE1E0E0FFF3F4F4FFBFBFBAF01A1A1A14FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0087878779F6F6F5FFF7F7F6FFF8F8 + F8FFFAFAFAFFFBFBFBFFFBFBFBFFFCFCFCFFFDFDFDFFFDFDFDFFFEFEFEFFFCFC + FCFFF6F6F6FFEAEAEAFFD4D4D4FFD9D8D7FFBEBEB7DC00000011FFFFFF00FFFF + FF00FFFFFF00FFFFFF0087878779F5F5F5FFF6F6F6FFF8F8F8FFF9F9F9FFFAFA + FAFFFBFBFBFFFCFCFCFFFCFCFCFFFDFDFDFFFEFEFEFFFEFEFEFFFDFDFDFFFAFA + FAFFF6F6F6FFF2F2F2FFF4F3F3FF7C7A7873FFFFFF00FFFFFF00FFFFFF00FFFF + FF0087878779F4F4F4FFF5F5F5FFF7F7F7FFF9F9F9FFFAFAFAFFFBFBFBFFFBFB + FBFFFCFCFCFFFCFCFCFFFDFDFDFFFEFEFEFFFEFEFEFFFEFEFEFFFEFEFEFFFDFD + FDFFFDFDFDFF87878779FFFFFF00FFFFFF00FFFFFF00FFFFFF0087878779F4F4 + F3FFF4F4F4FFF6F6F6FFF8F8F8FFF9F9F9FFFAFAFAFFFBFBFBFFFBFBFBFFFCFC + FCFFFCFCFCFFFDFDFDFFFDFDFDFFFDFDFDFFF9F9F9FFF6F6F6FFFEFEFEFF8787 + 8779FFFFFF00FFFFFF00FFFFFF00FFFFFF0087878779F3F3F2FFF3F3F3FFF5F5 + F5FFF7F7F6FFF8F8F8FFFAFAFAFFFAFAFAFFFBFBFBFFFBFBFBFFFCFCFCFFF0F0 + F0FFDEDEDEFFBDBDBDFFB7B7B7FFBEBEBEFFDEDEDEFF8585857AFFFFFF00FFFF + FF00FFFFFF00FFFFFF0087878779F2F2F1FFF2F2F2FFF4F4F4FFF5F5F5FFF7F7 + F7FFF8F8F8FFFAFAFAFFFAFAFAFFFBFBFBFFE9E9E9FF9494AEFF2D2DA8FF0A0A + B7FF0707BCFF0D0DBCFF2E2EA9FF343456B200000015FFFFFF00FFFFFF00FFFF + FF0087878779F1F1F0FFF1F1F1FFF3F3F2FFF4F4F4FFF6F6F5FFF7F7F7FFF8F8 + F8FFF9F9F9FFE7E7E7FF7575AEFF0606BBFF0004B3FF0010B0FF0023B1FF0024 + B4FF000FB8FF0101BCFD000068840000000AFFFFFF00FFFFFF0087878779F0F0 + F0FFF0F0EFFFF2F2F1FFF3F3F2FFF4F4F4FFF6F6F5FFF7F7F7FFF8F8F8FFACAC + C3FF0404B4FF0009ABFF3054C0FF0052C5FF006BD3FF0074D6FF2F7FD6FF0014 + B0FF0000B0F800004D4FFFFFFF00FFFFFF0087878779EFEFEFFFEFEFEEFFF0F0 + F0FFF2F2F1FFF3F3F2FFF4F4F4FFF5F5F5FFF2F2F2FF3434A7FF0005B1FF304B + BCFFFDFDFEFF7CAEDEFF008BDDFF7CC3EAFFFDFEFEFF2A6AC6FF000BB2FF0000 + 93C6FFFFFF00FFFFFF0087878779EEEEEDFFEEEEEDFFEFEFEEFFF0F0F0FFF1F1 + F1FFF3F3F2FFF4F4F3FFE3E3E2FF0E0EA5FF000DBCFF0038BDFF7CA2D6FFFFFF + FFFFB9D5EAFFFFFFFFFF78A9D9FF0052CCFF001AC0FF00009DF2FFFFFF00FFFF + FF0087878779EDEDECFFECECEBFFEEEEEDFFEFEFEEFFF0F0EFFFF1F1F0FFF2F2 + F2FFE2E2E1FF08089CFF0011C0FF0044CBFF004EB8FFB9CEE7FFFFFFFFFFB8C7 + DFFF004AB5FF003FCDFF0010BBFF00009BF5FFFFFF00FFFFFF0087878779EBEB + EAFFEBEBEAFFECECEBFFEDEDECFFEEEEEEFFEFEFEFFFF0F0F0FFEFEFEFFF0E0E + 9AFF010CB6FF0D3BC3FF8499CDFFFFFFFFFFBED1EDFFFFFFFFFF808FC7FF0C23 + B8FF0102B3FF000095ECFFFFFF00FFFFFF0087878779E9E9E8FFE9E8E7FFEAEA + E9FFECECEBFFEDEDECFFEEEEEDFFEFEFEEFFF0F0EFFF4949B0FF1013ADFF626F + CAFFFDFDFEFF97A6DBFF4461CCFF99A3DEFFFDFDFEFF5A5AC0FF0F0FAFFF0000 + 8DB4FFFFFF00FFFFFF0087878779E7E7E6FFE7E6E5FFE8E8E7FFEAEAE9FFEBEB + EAFFECECEBFFEDEDECFFEEEEEDFFC7C7E1FF080895FF494AC6FF8E8FE1FF7779 + DAFF797CDBFF7575D7FF8D8DDFFF4747C3FF000097F90000971FFFFFFF00FFFF + FF0064646466CECECEDAD1CFCFDCD1D1D1DCD2D1D1DCD2D2D2DCD2D2D2DCD2D2 + D2DCD3D3D2DCD3D3D3DC8A8ABDE71212A0FE6262CFFF9A9AE1FFA7A7E5FF9999 + E3FF6060D0FF0D0D9BF800009B4CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF000000B0170000A0A10404A1E42A2AC0ED0303BDD90000A4970000 + A923FFFFFF00FFFFFF00 + } + OnClick = btnEmptyImageClick + ParentColor = False + Rounding.RoundX = 12 + Rounding.RoundY = 12 + RoundingDropDown.RoundX = 1 + RoundingDropDown.RoundY = 1 + TextApplyGlobalOpacity = False + MemoryUsage = bmuHigh + end end object BGRAImageManipulation: TBGRAImageManipulation - Left = 170 - Height = 460 + Left = 198 + Height = 513 Top = 0 - Width = 457 + Width = 480 Align = alClient AnchorSize = 9 AspectRatio = '3:4' MinHeight = 40 MinWidth = 30 + EmptyImage.Allow = True + EmptyImage.ResolutionWidth = 21 + EmptyImage.ResolutionHeight = 29.7000007629395 + EmptyImage.ShowBorder = True + NewCropAreaDefault.AspectRatio = '3:4' OnCropAreaAdded = AddedCrop OnCropAreaDeleted = DeletedCrop OnCropAreaChanged = ChangedCrop @@ -1405,9 +1625,9 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo end object BCPanelCropAreas: TBCPanel Left = 0 - Height = 460 + Height = 513 Top = 0 - Width = 170 + Width = 198 Align = alLeft Background.Color = clSilver Background.ColorOpacity = 35 @@ -1465,7 +1685,7 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo ParentShowHint = False end object btBox_Del: TBGRASpeedButton - Left = 147 + Left = 149 Height = 22 Hint = 'Remove this Box' Top = 21 @@ -1492,8 +1712,8 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo object BCPanelCropAreaLoad: TBCPanel Left = 1 Height = 106 - Top = 353 - Width = 168 + Top = 406 + Width = 196 Align = alBottom Background.Color = clBtnFace Background.Gradient1.StartColor = clWhite @@ -1976,9 +2196,9 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo end object BCPanelCropArea: TBCPanel Left = 0 - Height = 300 + Height = 360 Top = 48 - Width = 170 + Width = 186 Background.Color = clBtnFace Background.Gradient1.StartColor = clWhite Background.Gradient1.EndColor = clBlack @@ -2000,6 +2220,7 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo BevelOuter = bvNone BevelWidth = 1 Border.Style = bboNone + Enabled = False FontEx.Color = clDefault FontEx.FontQuality = fqSystemClearType FontEx.Shadow = False @@ -2044,82 +2265,6 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Rounding.RoundX = 1 Rounding.RoundY = 1 end - object edLeft: TBCTrackbarUpdown - Left = 56 - Height = 24 - Top = 64 - Width = 103 - AllowNegativeValues = False - BarExponent = 1 - Increment = 1 - LongTimeInterval = 400 - MinValue = 0 - MaxValue = 100 - OnChange = edLeftChange - Value = 50 - ShortTimeInterval = 100 - Background.Color = clWindow - Background.Gradient1.StartColor = clWhite - Background.Gradient1.EndColor = clBlack - Background.Gradient1.GradientType = gtLinear - Background.Gradient1.Point1XPercent = 0 - Background.Gradient1.Point1YPercent = 0 - Background.Gradient1.Point2XPercent = 0 - Background.Gradient1.Point2YPercent = 100 - Background.Gradient2.StartColor = clWhite - Background.Gradient2.EndColor = clBlack - Background.Gradient2.GradientType = gtLinear - Background.Gradient2.Point1XPercent = 0 - Background.Gradient2.Point1YPercent = 0 - Background.Gradient2.Point2XPercent = 0 - Background.Gradient2.Point2YPercent = 100 - Background.Gradient1EndPercent = 35 - Background.Style = bbsColor - ButtonBackground.Gradient1.StartColor = clBtnShadow - ButtonBackground.Gradient1.EndColor = clBtnFace - ButtonBackground.Gradient1.GradientType = gtLinear - ButtonBackground.Gradient1.Point1XPercent = 0 - ButtonBackground.Gradient1.Point1YPercent = -50 - ButtonBackground.Gradient1.Point2XPercent = 0 - ButtonBackground.Gradient1.Point2YPercent = 50 - ButtonBackground.Gradient2.StartColor = clBtnFace - ButtonBackground.Gradient2.EndColor = clBtnShadow - ButtonBackground.Gradient2.GradientType = gtLinear - ButtonBackground.Gradient2.Point1XPercent = 0 - ButtonBackground.Gradient2.Point1YPercent = 50 - ButtonBackground.Gradient2.Point2XPercent = 0 - ButtonBackground.Gradient2.Point2YPercent = 150 - ButtonBackground.Gradient1EndPercent = 50 - ButtonBackground.Style = bbsGradient - ButtonDownBackground.Color = clBtnShadow - ButtonDownBackground.Gradient1.StartColor = clWhite - ButtonDownBackground.Gradient1.EndColor = clBlack - ButtonDownBackground.Gradient1.GradientType = gtLinear - ButtonDownBackground.Gradient1.Point1XPercent = 0 - ButtonDownBackground.Gradient1.Point1YPercent = 0 - ButtonDownBackground.Gradient1.Point2XPercent = 0 - ButtonDownBackground.Gradient1.Point2YPercent = 100 - ButtonDownBackground.Gradient2.StartColor = clWhite - ButtonDownBackground.Gradient2.EndColor = clBlack - ButtonDownBackground.Gradient2.GradientType = gtLinear - ButtonDownBackground.Gradient2.Point1XPercent = 0 - ButtonDownBackground.Gradient2.Point1YPercent = 0 - ButtonDownBackground.Gradient2.Point2XPercent = 0 - ButtonDownBackground.Gradient2.Point2YPercent = 100 - ButtonDownBackground.Gradient1EndPercent = 35 - ButtonDownBackground.Style = bbsColor - Border.Color = clWindowText - Border.Style = bboSolid - Rounding.RoundX = 1 - Rounding.RoundY = 1 - Font.Color = clWindowText - Font.Name = 'Arial' - HasTrackBar = True - ArrowColor = clBtnText - TabOrder = 0 - TabStop = True - UseDockManager = False - end object BCLabel2: TBCLabel Left = 20 Height = 15 @@ -2153,82 +2298,6 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Rounding.RoundX = 1 Rounding.RoundY = 1 end - object edTop: TBCTrackbarUpdown - Left = 56 - Height = 24 - Top = 92 - Width = 103 - AllowNegativeValues = False - BarExponent = 1 - Increment = 1 - LongTimeInterval = 400 - MinValue = 0 - MaxValue = 100 - OnChange = edTopChange - Value = 50 - ShortTimeInterval = 100 - Background.Color = clWindow - Background.Gradient1.StartColor = clWhite - Background.Gradient1.EndColor = clBlack - Background.Gradient1.GradientType = gtLinear - Background.Gradient1.Point1XPercent = 0 - Background.Gradient1.Point1YPercent = 0 - Background.Gradient1.Point2XPercent = 0 - Background.Gradient1.Point2YPercent = 100 - Background.Gradient2.StartColor = clWhite - Background.Gradient2.EndColor = clBlack - Background.Gradient2.GradientType = gtLinear - Background.Gradient2.Point1XPercent = 0 - Background.Gradient2.Point1YPercent = 0 - Background.Gradient2.Point2XPercent = 0 - Background.Gradient2.Point2YPercent = 100 - Background.Gradient1EndPercent = 35 - Background.Style = bbsColor - ButtonBackground.Gradient1.StartColor = clBtnShadow - ButtonBackground.Gradient1.EndColor = clBtnFace - ButtonBackground.Gradient1.GradientType = gtLinear - ButtonBackground.Gradient1.Point1XPercent = 0 - ButtonBackground.Gradient1.Point1YPercent = -50 - ButtonBackground.Gradient1.Point2XPercent = 0 - ButtonBackground.Gradient1.Point2YPercent = 50 - ButtonBackground.Gradient2.StartColor = clBtnFace - ButtonBackground.Gradient2.EndColor = clBtnShadow - ButtonBackground.Gradient2.GradientType = gtLinear - ButtonBackground.Gradient2.Point1XPercent = 0 - ButtonBackground.Gradient2.Point1YPercent = 50 - ButtonBackground.Gradient2.Point2XPercent = 0 - ButtonBackground.Gradient2.Point2YPercent = 150 - ButtonBackground.Gradient1EndPercent = 50 - ButtonBackground.Style = bbsGradient - ButtonDownBackground.Color = clBtnShadow - ButtonDownBackground.Gradient1.StartColor = clWhite - ButtonDownBackground.Gradient1.EndColor = clBlack - ButtonDownBackground.Gradient1.GradientType = gtLinear - ButtonDownBackground.Gradient1.Point1XPercent = 0 - ButtonDownBackground.Gradient1.Point1YPercent = 0 - ButtonDownBackground.Gradient1.Point2XPercent = 0 - ButtonDownBackground.Gradient1.Point2YPercent = 100 - ButtonDownBackground.Gradient2.StartColor = clWhite - ButtonDownBackground.Gradient2.EndColor = clBlack - ButtonDownBackground.Gradient2.GradientType = gtLinear - ButtonDownBackground.Gradient2.Point1XPercent = 0 - ButtonDownBackground.Gradient2.Point1YPercent = 0 - ButtonDownBackground.Gradient2.Point2XPercent = 0 - ButtonDownBackground.Gradient2.Point2YPercent = 100 - ButtonDownBackground.Gradient1EndPercent = 35 - ButtonDownBackground.Style = bbsColor - Border.Color = clWindowText - Border.Style = bboSolid - Rounding.RoundX = 1 - Rounding.RoundY = 1 - Font.Color = clWindowText - Font.Name = 'Arial' - HasTrackBar = True - ArrowColor = clBtnText - TabOrder = 1 - TabStop = True - UseDockManager = False - end object BCLabel3: TBCLabel Left = 8 Height = 15 @@ -2262,82 +2331,6 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Rounding.RoundX = 1 Rounding.RoundY = 1 end - object edWidth: TBCTrackbarUpdown - Left = 56 - Height = 24 - Top = 120 - Width = 103 - AllowNegativeValues = False - BarExponent = 1 - Increment = 1 - LongTimeInterval = 400 - MinValue = 0 - MaxValue = 100 - OnChange = edWidthChange - Value = 50 - ShortTimeInterval = 100 - Background.Color = clWindow - Background.Gradient1.StartColor = clWhite - Background.Gradient1.EndColor = clBlack - Background.Gradient1.GradientType = gtLinear - Background.Gradient1.Point1XPercent = 0 - Background.Gradient1.Point1YPercent = 0 - Background.Gradient1.Point2XPercent = 0 - Background.Gradient1.Point2YPercent = 100 - Background.Gradient2.StartColor = clWhite - Background.Gradient2.EndColor = clBlack - Background.Gradient2.GradientType = gtLinear - Background.Gradient2.Point1XPercent = 0 - Background.Gradient2.Point1YPercent = 0 - Background.Gradient2.Point2XPercent = 0 - Background.Gradient2.Point2YPercent = 100 - Background.Gradient1EndPercent = 35 - Background.Style = bbsColor - ButtonBackground.Gradient1.StartColor = clBtnShadow - ButtonBackground.Gradient1.EndColor = clBtnFace - ButtonBackground.Gradient1.GradientType = gtLinear - ButtonBackground.Gradient1.Point1XPercent = 0 - ButtonBackground.Gradient1.Point1YPercent = -50 - ButtonBackground.Gradient1.Point2XPercent = 0 - ButtonBackground.Gradient1.Point2YPercent = 50 - ButtonBackground.Gradient2.StartColor = clBtnFace - ButtonBackground.Gradient2.EndColor = clBtnShadow - ButtonBackground.Gradient2.GradientType = gtLinear - ButtonBackground.Gradient2.Point1XPercent = 0 - ButtonBackground.Gradient2.Point1YPercent = 50 - ButtonBackground.Gradient2.Point2XPercent = 0 - ButtonBackground.Gradient2.Point2YPercent = 150 - ButtonBackground.Gradient1EndPercent = 50 - ButtonBackground.Style = bbsGradient - ButtonDownBackground.Color = clBtnShadow - ButtonDownBackground.Gradient1.StartColor = clWhite - ButtonDownBackground.Gradient1.EndColor = clBlack - ButtonDownBackground.Gradient1.GradientType = gtLinear - ButtonDownBackground.Gradient1.Point1XPercent = 0 - ButtonDownBackground.Gradient1.Point1YPercent = 0 - ButtonDownBackground.Gradient1.Point2XPercent = 0 - ButtonDownBackground.Gradient1.Point2YPercent = 100 - ButtonDownBackground.Gradient2.StartColor = clWhite - ButtonDownBackground.Gradient2.EndColor = clBlack - ButtonDownBackground.Gradient2.GradientType = gtLinear - ButtonDownBackground.Gradient2.Point1XPercent = 0 - ButtonDownBackground.Gradient2.Point1YPercent = 0 - ButtonDownBackground.Gradient2.Point2XPercent = 0 - ButtonDownBackground.Gradient2.Point2YPercent = 100 - ButtonDownBackground.Gradient1EndPercent = 35 - ButtonDownBackground.Style = bbsColor - Border.Color = clWindowText - Border.Style = bboSolid - Rounding.RoundX = 1 - Rounding.RoundY = 1 - Font.Color = clWindowText - Font.Name = 'Arial' - HasTrackBar = True - ArrowColor = clBtnText - TabOrder = 2 - TabStop = True - UseDockManager = False - end object BCLabel4: TBCLabel Left = 4 Height = 15 @@ -2371,82 +2364,6 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Rounding.RoundX = 1 Rounding.RoundY = 1 end - object edHeight: TBCTrackbarUpdown - Left = 56 - Height = 24 - Top = 148 - Width = 103 - AllowNegativeValues = False - BarExponent = 1 - Increment = 1 - LongTimeInterval = 400 - MinValue = 0 - MaxValue = 100 - OnChange = edHeightChange - Value = 50 - ShortTimeInterval = 100 - Background.Color = clWindow - Background.Gradient1.StartColor = clWhite - Background.Gradient1.EndColor = clBlack - Background.Gradient1.GradientType = gtLinear - Background.Gradient1.Point1XPercent = 0 - Background.Gradient1.Point1YPercent = 0 - Background.Gradient1.Point2XPercent = 0 - Background.Gradient1.Point2YPercent = 100 - Background.Gradient2.StartColor = clWhite - Background.Gradient2.EndColor = clBlack - Background.Gradient2.GradientType = gtLinear - Background.Gradient2.Point1XPercent = 0 - Background.Gradient2.Point1YPercent = 0 - Background.Gradient2.Point2XPercent = 0 - Background.Gradient2.Point2YPercent = 100 - Background.Gradient1EndPercent = 35 - Background.Style = bbsColor - ButtonBackground.Gradient1.StartColor = clBtnShadow - ButtonBackground.Gradient1.EndColor = clBtnFace - ButtonBackground.Gradient1.GradientType = gtLinear - ButtonBackground.Gradient1.Point1XPercent = 0 - ButtonBackground.Gradient1.Point1YPercent = -50 - ButtonBackground.Gradient1.Point2XPercent = 0 - ButtonBackground.Gradient1.Point2YPercent = 50 - ButtonBackground.Gradient2.StartColor = clBtnFace - ButtonBackground.Gradient2.EndColor = clBtnShadow - ButtonBackground.Gradient2.GradientType = gtLinear - ButtonBackground.Gradient2.Point1XPercent = 0 - ButtonBackground.Gradient2.Point1YPercent = 50 - ButtonBackground.Gradient2.Point2XPercent = 0 - ButtonBackground.Gradient2.Point2YPercent = 150 - ButtonBackground.Gradient1EndPercent = 50 - ButtonBackground.Style = bbsGradient - ButtonDownBackground.Color = clBtnShadow - ButtonDownBackground.Gradient1.StartColor = clWhite - ButtonDownBackground.Gradient1.EndColor = clBlack - ButtonDownBackground.Gradient1.GradientType = gtLinear - ButtonDownBackground.Gradient1.Point1XPercent = 0 - ButtonDownBackground.Gradient1.Point1YPercent = 0 - ButtonDownBackground.Gradient1.Point2XPercent = 0 - ButtonDownBackground.Gradient1.Point2YPercent = 100 - ButtonDownBackground.Gradient2.StartColor = clWhite - ButtonDownBackground.Gradient2.EndColor = clBlack - ButtonDownBackground.Gradient2.GradientType = gtLinear - ButtonDownBackground.Gradient2.Point1XPercent = 0 - ButtonDownBackground.Gradient2.Point1YPercent = 0 - ButtonDownBackground.Gradient2.Point2XPercent = 0 - ButtonDownBackground.Gradient2.Point2YPercent = 100 - ButtonDownBackground.Gradient1EndPercent = 35 - ButtonDownBackground.Style = bbsColor - Border.Color = clWindowText - Border.Style = bboSolid - Rounding.RoundX = 1 - Rounding.RoundY = 1 - Font.Color = clWindowText - Font.Name = 'Arial' - HasTrackBar = True - ArrowColor = clBtnText - TabOrder = 3 - TabStop = True - UseDockManager = False - end object edUnit_Type: TComboBox Left = 56 Height = 23 @@ -2457,11 +2374,12 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo ItemIndex = 0 Items.Strings = ( 'pixels' - 'mm' - 'percent' + 'inchs' + 'cm' ) + OnChange = edUnit_TypeChange Style = csDropDownList - TabOrder = 4 + TabOrder = 0 Text = 'pixels' end object BCLabel5: TBCLabel @@ -2537,20 +2455,20 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Width = 103 AutoSize = False OnEditingDone = edNameChange - TabOrder = 5 + TabOrder = 1 end object edAspectPersonal: TEdit - Left = 47 + Left = 45 Height = 23 - Top = 256 + Top = 330 Width = 87 AutoSize = False - TabOrder = 6 + TabOrder = 2 end object rgAspect: TRadioGroup - Left = 22 - Height = 76 - Top = 174 + Left = 20 + Height = 68 + Top = 256 Width = 137 AutoFill = True Caption = 'Aspect Ratio' @@ -2561,7 +2479,7 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo ChildSizing.ShrinkVertical = crsScaleChilds ChildSizing.Layout = cclLeftToRightThenTopToBottom ChildSizing.ControlsPerLine = 1 - ClientHeight = 56 + ClientHeight = 48 ClientWidth = 133 Items.Strings = ( 'Parent' @@ -2569,12 +2487,12 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo 'Personal' ) OnSelectionChanged = rgAspectSelectionChanged - TabOrder = 7 + TabOrder = 3 end object btApplyAspectRatio: TSpeedButton - Left = 135 + Left = 133 Height = 22 - Top = 257 + Top = 331 Width = 23 Glyph.Data = { C6070000424DC607000000000000360000002800000016000000160000000100 @@ -2643,15 +2561,614 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo } OnClick = btApplyAspectRatioClick end - object SpeedButton1: TSpeedButton - Left = 8 - Height = 19 - Top = 280 - Width = 32 - AutoSize = True - Caption = ':Tests' - OnClick = SpeedButton1Click + object edLeft: TFloatSpinEdit + Left = 56 + Height = 23 + Top = 64 + Width = 103 + DecimalPlaces = 3 + Font.Color = clWindowText + Font.Name = 'Arial' + MaxValue = 100 + OnChange = edLeftChange + ParentFont = False + TabOrder = 4 + Value = 50 end + object edTop: TFloatSpinEdit + Left = 56 + Height = 23 + Top = 92 + Width = 103 + DecimalPlaces = 3 + Font.Color = clWindowText + Font.Name = 'Arial' + MaxValue = 100 + OnChange = edTopChange + ParentFont = False + TabOrder = 5 + Value = 50 + end + object edWidth: TFloatSpinEdit + Left = 56 + Height = 23 + Top = 120 + Width = 103 + DecimalPlaces = 3 + Font.Color = clWindowText + Font.Name = 'Arial' + MaxValue = 100 + OnChange = edWidthChange + ParentFont = False + TabOrder = 6 + Value = 50 + end + object edHeight: TFloatSpinEdit + Left = 56 + Height = 23 + Top = 148 + Width = 103 + DecimalPlaces = 3 + Font.Color = clWindowText + Font.Name = 'Arial' + MaxValue = 100 + OnChange = edHeightChange + ParentFont = False + TabOrder = 7 + Value = 50 + end + object Label1: TLabel + Left = 7 + Height = 15 + Top = 224 + Width = 46 + Caption = 'Z Order :' + end + object btZFront: TSpeedButton + Left = 57 + Height = 22 + Hint = 'To Front' + Top = 224 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00004E00070050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900660003FFFFFF00FFFFFF00004E + 003C2F6B2FFE3C783CFF307930FF267C26FF1C801CFF168416FF098608FF0C90 + 0BFF10960FFF149712FF179615FF21941EFF1A9D15D6FFFFFF00FFFFFF00FFFF + FF00185D18C472A872FD5F9F5FFF469246FF2D8A2DFF198919FF008900FF0096 + 00FF009F00FF00A000FF009700FF219D1EFC038C0050FFFFFF00FFFFFF00FFFF + FF000058000C276927E864A764FE4A9B4AFF319431FF1D951DFF009600FF00A7 + 00FF00B400FF00B700FF18AD17FC088D0486FFFFFF00FFFFFF00FFFFFF00FFFF + FF00004E0007004C0031347D34F850A350FF379C37FF239E23FF009D00FF00B2 + 00FF00C500FF0EC60DFB0C910ABB0050000900660003FFFFFF00FFFFFF00004E + 003C357235FE438343FF388138FF4FA04FFF3B9F3BFF249F24FF04A004FF00B3 + 00FF00C700FF1BC11AFF17AD15FF21A41EFF1A9715D6FFFFFF00FFFFFF00FFFF + FF001A5D1AC380BA80FD72B572FF58A758FF40A040FF279D27FF089C08FF00AA + 00FF00B800FF00BC00FF00B000FF24A121FC03870052FFFFFF00FFFFFF00FFFF + FF000040000A296B29E775B475FE5DA85DFF449F44FF2B992BFF099109FF009A + 00FF00A400FF00A500FF1CA21BFC08860488FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0000510028367836F763A863FF499B49FF309230FF0A820AFF0088 + 00FF008E00FF129411FB108A0CBEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00004E0053408340FB4E974EFF358B35FF0B720BFF0073 + 00FF097E09FC138610E100520005FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0004530489418541FC3A833AFF0C600CFF0361 + 03FE147D12F400780020FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000A5D0AC03A793AFC0B4C0BFF116B + 10FB0369004CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000040000A156314E6266425FE0469 + 027EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005B002829782787FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btZFrontClick + end + object btZBack: TSpeedButton + Left = 81 + Height = 22 + Hint = 'To Back' + Top = 224 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005B00280461027DFFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000040000A156714E6176416FE0469 + 027EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000A5E0AC03A853AFC0B600BFF1174 + 10FB0369004CFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0004530489418D41FC3A8F3AFF0C720CFF0375 + 03FE148412F400780020FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00004E0053408840FB4E9F4EFF359635FF0B830BFF0088 + 00FF099109FC138A10E100520005FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0000510028367B36F763AD63FF49A249FF309C30FF0A910AFF009A + 00FF00A400FF12A611FB108A0CBEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF000040000A296C29E775B675FE5DAB5DFF44A344FF2BA02BFF099C09FF00AA + 00FF00B800FF00BC00FF1CAE1BFC08860488FFFFFF00FFFFFF00FFFFFF00FFFF + FF001A5D1AC380BA80FD72B672FF58A958FF40A240FF27A127FF08A208FF00B3 + 00FF00C700FF00D300FF00BE00FF24A421FC03870052FFFFFF00FFFFFF00004D + 0021357235FE438343FF388138FF4FA04FFF3B9F3BFF249F24FF049F04FF00B2 + 00FF00C500FF1BBE1AFF17AC15FF21A31EFF058C00D2FFFFFF00FFFFFF00FFFF + FF00004E0007004C0031347B34F950A050FF379837FF239823FF009600FF00A7 + 00FF00B400FF0EB40DFB0C9B0ABB0050000900660003FFFFFF00FFFFFF00FFFF + FF000058000C276827E864A464FE4A964AFF318E31FF1D8B1DFF008900FF0096 + 00FF009F00FF00A000FF18A117FC088D0486FFFFFF00FFFFFF00FFFFFF00FFFF + FF00185C18C472A572FD5F9B5FFF468B46FF2D812DFF197C19FF007800FF0083 + 00FF008900FF008900FF008100FF21951EFC038C0050FFFFFF00FFFFFF00004D + 00212F6A2FFE3C743CFF307430FF267626FF1A781AFF117A11FF017800FF017F + 00FF018200FF028200FF178C15FF218B1EFF059100D2FFFFFF00FFFFFF00FFFF + FF00004E00070050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900660003FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btZBackClick + end + object btZDown: TSpeedButton + Left = 134 + Height = 22 + Hint = 'Down' + Top = 224 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000058005303610058FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005100341E6A1DF90C620BFA0465 + 003EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0000420012166715EB388238FE045D04FE0E76 + 0CF0006E0018FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00008000010D5D0DCB469246FC348C34FF057005FF077A + 07FB0D7F0BD800800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00055205984E974EFC479C47FF2F942FFF068206FF008A + 00FF0E920DFB0C8109AEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00004E00614D904DFC5BA95BFF43A043FF2D9D2DFF029102FF009D + 00FF00A500FF17A015FC067F0277FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0000480032418141F970B670FF57A957FF3EA33EFF2AA22AFF009D00FF00AE + 00FF00BA00FF00BA00FF1BA118FB04830044FFFFFF00FFFFFF00FFFFFF000042 + 0012327032ED83C183FE6BB26BFF52A752FF3AA23AFF25A425FF00A300FF00B8 + 00FF00CC00FF00D000FF05B805FE1A9816F300870019FFFFFF00FFFFFF00004D + 00854A844AFF458545FF3A853AFF2D882DFF228B22FF178F17FF019000FF019E + 00FF02A900FF02AB00FF18AA16FF28A325FF038D009AFFFFFF00FFFFFF000000 + 0001005000090050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900000001FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btZDownClick + end + object btZUp: TSpeedButton + Left = 110 + Height = 22 + Hint = 'Up' + Top = 224 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0001005000090050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900000001FFFFFF00FFFFFF00004D + 00854A844AFF458545FF3A853AFF2D892DFF258D25FF1C931CFF0A9609FF0DA4 + 0CFF11B00FFF15B413FF18AB16FF29A427FF068E039BFFFFFF00FFFFFF000042 + 0012327032ED83C083FE6BB16BFF52A552FF3A9F3AFF259F25FF009D00FF00AE + 00FF00BB00FF00BA00FF05AC05FE1A9616F300870019FFFFFF00FFFFFF00FFFF + FF0000480032418041F970B370FF57A557FF3E9D3EFF2A9A2AFF009000FF009D + 00FF00A500FF00A400FF038E00FB04830044FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00004E00614D8C4DFC5BA45BFF439943FF2D932DFF028002FF008A + 00FF008F00FF179515FC067F0277FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00055205984E924EFC479447FF2F872FFF067106FF0075 + 00FF0E810DFB0C8109AEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00008000010D5A0DCB468946FC347F34FF055D05FF0767 + 07FB0D7D0BD800800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0000420012166215EB387638FE044804FE0E71 + 0CF0006E0018FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005100341E631DF91B661AFA0465 + 003EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000580053337F3064FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btZUpClick + end + object Label2: TLabel + Left = 14 + Height = 15 + Top = 176 + Width = 40 + Caption = 'Rotate :' + end + object btCRotateLeft: TSpeedButton + Left = 58 + Height = 22 + Hint = 'Rotate Left' + Top = 176 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000000000 + 0000000000000000000000000000000000000000000000000000000000002ECE + 560114BE27021DC4360200000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000002AC84F0123C5 + 43031CC1340A1DC3360E20B73A0F068C0C020000000000000000000000000000 + 0000000000000000000000000000000000000000000025C6460223C441041EC2 + 380817BF2C1610BB1E1C0ABA13221CA531250000000000000000000000000000 + 00000000000010BB1E0116BE29020000000024C443011FB73B051FBC380925C8 + 421011BC21260BB9152F04B608370CAD1343066F0B6000620012000000000000 + 00000000000009B812010EBB1B0821B73E0524AC4301006000080064003B026B + 03680F921C6505B60A4500B4005000B4005A0A8A1095007C006F000000000000 + 00000000000010B7200115BA290523AA43040000000000000000000000000081 + 0015018601DB0CAE176B00B4006C00B40079099D11A4008C00CC007C0068007F + 00CC008300DC008600EA008A00F8008C00FF008C00FF008C00ED008C002D0000 + 0000008D019F06970BB801B4018D03B5039C0AAF0FB0008C00F9008C01F01DB2 + 32F91FB633FD25B836FD24BA36FE20BC32FE21BD39FA008C00EA008C002A0000 + 0000008D019F08990DCB0BB50BB216B916C419B41DD7008C00F9018D01F422BD + 27FF24BD26FF22BC23FF11B812FF0FAF17FF018D03F4008C004E00000000008C + 001A018C01F40DAD12DD1DBB1EEC24BD26F81BA620FD018C01CF018D01F436C3 + 3EFF33C438FF2EC133FF05B505FF10A119FD018C02F4018C01B8018C02AD018B + 02F60A970EFD17BB18FF33C438FF33C438FF169919FE008C0093018D02F446CA + 50FF43CB4DFF43CB4DFF37C740FF12B914FF0DB514FF11A418FE099F10FE0AB0 + 0FFF20BE23FF43CB4CFF43CB4DFF3FC248FF028D02F5008C0033018D02F457D1 + 65FF58D266FF56D466FF55D465FF54D364FF54D25EFF34C83CFF31C63AFF49CF + 55FF56D466FF55D465FF58D667FF109814F8008C008300000000018D02F44CC6 + 5CFF028F04F90F9A14FB58D069FF67DF7FFF67DF7FFF67DF7FFF67DF7FFF67DF + 7FFF67DF7FFF5ED772FF119C17F8018D01C6008C000500000000028E03DB028E + 02F4008C004E038E0566039005F72BAE35FF4EC65DFF6EDB85FF6EDB86FF48C4 + 58FF29AE32FF039004F5018D0176008C00020000000000000000008C0019008C + 001B0000000000000000008C001D028E037B0B950FC109920AF0069108EE0491 + 07BD018D0180008C002500000000000000000000000000000000 + } + OnClick = btCRotateLeftClick + end + object btCRotateRight: TSpeedButton + Left = 82 + Height = 22 + Hint = 'Rotate Right' + Top = 176 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF0000BF00001DC4360214BE27022ECE5601FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00068C0C0220B73A0F1DC3360E1CC1340A23C543032AC84F01FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000099 + 00001CA531250ABA132210BB1E1C17BF2C161EC2380823C4410425C64602FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000620012066F + 0B600CAD134304B608370BB9152F11BC212625C842101FBC38091FB73B0524C4 + 4301FFFFFF0016BE290210BB1E01FFFFFF00FFFFFF00FFFFFF00007C006F0A8A + 109500B4005A00B4005005B60A450F921C65026B03680064003B0060000824AC + 430121B73E050EBB1B0809B81201FFFFFF00FFFFFF00FFFFFF00008C00CC099D + 11A400B4007900B4006C0CAE176B018601DB00810015FFFFFF00FFFFFF00FFFF + FF0023AA430415BA290510B72001FFFFFF00FFFFFF00FFFFFF00008C00F90AAF + 0FB003B5039C01B4018D06970BB8008D019FFFFFFF00008C002D008C00ED008C + 00FF008C00FF008A00F8008600EA008300DC007F00CC007C0068008C00F919B4 + 1DD716B916C40BB50BB208990DCB008D019FFFFFFF00008C002A008C00EA21BD + 39FA20BC32FE24BA36FE25B836FD1FB633FD1DB232F9008C01F0018C01CF1BA6 + 20FD24BD26F81DBB1EEC0DAD12DD018C01F4008C001AFFFFFF00008C004E018D + 03F40FAF17FF11B812FF22BC23FF24BD26FF22BD27FF018D01F4008C00931699 + 19FE33C438FF33C438FF17BB18FF0A970EFD018B02F6018C02AD018C01B8018C + 02F410A119FD05B505FF2EC133FF33C438FF36C33EFF018D01F4008C0033028D + 02F53FC248FF43CB4DFF43CB4CFF20BE23FF0AB00FFF099F10FE11A418FE0DB5 + 14FF12B914FF37C740FF43CB4DFF43CB4DFF46CA50FF018D02F4FFFFFF00008C + 0083109814F858D667FF55D465FF56D466FF49CF55FF31C63AFF34C83CFF54D2 + 5EFF54D364FF55D465FF56D466FF58D266FF57D165FF018D02F4FFFFFF00008C + 0005018D01C6119C17F85ED772FF67DF7FFF67DF7FFF67DF7FFF67DF7FFF67DF + 7FFF67DF7FFF58D069FF0F9A14FB028F04F94CC65CFF018D02F4FFFFFF00FFFF + FF00008C0002018D0176039004F529AE32FF48C458FF6EDB86FF6EDB85FF4EC6 + 5DFF2BAE35FF039005F7038E0566008C004E028E02F4028E03DBFFFFFF00FFFF + FF00FFFFFF00FFFFFF00008C0025018D0180049107BD069108EE09920AF00B95 + 0FC1028E037B008C001DFFFFFF00FFFFFF00008C001B008C0019 + } + OnClick = btCRotateRightClick + end + object Label3: TLabel + Left = 28 + Height = 15 + Top = 200 + Width = 25 + Caption = 'Flip :' + end + object btCFlipVUp: TSpeedButton + Left = 58 + Height = 22 + Hint = 'Flip Vertical Up' + Top = 200 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000000 + 0001005000090050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900000001FFFFFF00FFFFFF00004D + 00854A844AFF458545FF3A853AFF2D892DFF258D25FF1C931CFF0A9609FF0DA4 + 0CFF11B00FFF15B413FF18AB16FF29A427FF068E039BFFFFFF00FFFFFF000042 + 0012327032ED83C083FE6BB16BFF52A552FF3A9F3AFF259F25FF009D00FF00AE + 00FF00BB00FF00BA00FF05AC05FE1A9616F300870019FFFFFF00FFFFFF00FFFF + FF0000480032418041F970B370FF57A557FF3E9D3EFF2A9A2AFF009000FF009D + 00FF00A500FF00A400FF038E00FB04830044FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00004E00614D8C4DFC5BA45BFF439943FF2D932DFF028002FF008A + 00FF008F00FF179515FC067F0277FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00055205984E924EFC479447FF2F872FFF067106FF0075 + 00FF0E810DFB0C8109AEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00008000010D5A0DCB468946FC347F34FF055D05FF0767 + 07FB0D7D0BD800800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0000420012166215EB387638FE044804FE0E71 + 0CF0006E0018FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005100341E631DF91B661AFA0465 + 003EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000580053337F3064FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btCFlipVUpClick + end + object btCFlipVDown: TSpeedButton + Left = 82 + Height = 22 + Hint = 'Flip Vertical Down' + Top = 200 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000058005303610058FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00005100341E6A1DF90C620BFA0465 + 003EFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF0000420012166715EB388238FE045D04FE0E76 + 0CF0006E0018FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00008000010D5D0DCB469246FC348C34FF057005FF077A + 07FB0D7F0BD800800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00055205984E974EFC479C47FF2F942FFF068206FF008A + 00FF0E920DFB0C8109AEFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00004E00614D904DFC5BA95BFF43A043FF2D9D2DFF029102FF009D + 00FF00A500FF17A015FC067F0277FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0000480032418141F970B670FF57A957FF3EA33EFF2AA22AFF009D00FF00AE + 00FF00BA00FF00BA00FF1BA118FB04830044FFFFFF00FFFFFF00FFFFFF000042 + 0012327032ED83C183FE6BB26BFF52A752FF3AA23AFF25A425FF00A300FF00B8 + 00FF00CC00FF00D000FF05B805FE1A9816F300870019FFFFFF00FFFFFF00004D + 00854A844AFF458545FF3A853AFF2D882DFF228B22FF178F17FF019000FF019E + 00FF02A900FF02AB00FF18AA16FF28A325FF038D009AFFFFFF00FFFFFF000000 + 0001005000090050000900500009005000090050000900500009005000090050 + 00090050000900500009005000090050000900000001FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btCFlipVDownClick + end + object btCFlipHLeft: TSpeedButton + Left = 111 + Height = 22 + Hint = 'Flip Horizzontal Left' + Top = 200 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0000820015068E039300000001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000480 + 003A1E9A1AF22CA529FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000480026F1F9D + 1EFB07AD07FE18AB16FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00008000010C8209A71B9719FC01A4 + 01FF00BA00FF15B413FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00007100140F7D0DD4118210FB008F00FF00A5 + 00FF00BB00FF11B00FFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000561003610700EED096809FB007500FF008A00FF009D + 00FF00AE00FF0DA40CFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00035E00550E5C0DF8034703FE015B01FF026F02FF007F00FF0090 + 00FF009D00FF0A9609FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00005900521F671FF9397639FE337E33FF2F872FFF2D922DFF2799 + 27FF239E23FF1C931CFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0000520032196618EB468746FC479447FF439943FF3E9D + 3EFF3A9F3AFF248D24FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00004400120F5C0FCB4F934FFC5BA45BFF57A5 + 57FF52A552FF2D892DFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF0000800001075307994F8E4FFC70B3 + 70FF6BB16BFF3A853AFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00004E00604381 + 43F983C083FE458545FF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF000048 + 0032327032ED4A844AFF00500009FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF0000420012004E008700000001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btCFlipHLeftClick + end + object btCFlipHRight: TSpeedButton + Left = 134 + Height = 22 + Hint = 'Flip Horizzontal Right' + Top = 200 + Width = 23 + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0006890351078A0366FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00159611BE2EA92CFF118F0CAC00800001FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF0013920FBB0BBC0BFF17B116FB159112D800770015FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000F8D0CB809D509FF00C500FF0CB00CFC169214F00575 + 0038FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000E880BB508D008FF00C400FF00B000FF059B05FE027E + 00F90272006BFFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF000C8209B106BB06FF00B400FF00A600FF009400FF007F + 00FF127A11FB086F06A200800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00077C06AF04A604FF00A100FF009700FF018801FF0378 + 03FF006300FF0A5C0AFB086608CC00000001FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00057404AC2AA52AFF25A325FF2AA02AFF2E992EFF3190 + 31FF368836FF327A32FC0D630CCB00000001FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00036C02A93EA43EFF3CA23CFF40A240FF459E45FF499A + 49FF327F32FB0559059900800001FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00006200A655A855FF55A955FF59A959FF5CA75CFE2D78 + 2DF900500060FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00005700A66DB36DFF6DB46DFF6BAF6BFD236B23EB0049 + 0031FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00004E00A685C185FF70AC70FD195F19CD00440012FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00004E00A67BAD7BFE0D570D9B00800001FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00004F004A0852085CFFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFF + FF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00FFFFFF00 + } + OnClick = btCFlipHRightClick + end + object btCropDuplicateOp: TSpeedButton + Left = 161 + Height = 22 + Hint = 'Duplicate when Rotate/Flip' + Top = 192 + Width = 23 + AllowAllUp = True + Flat = True + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000000000000000 + 0000000000000000000000000012000000570000005B0000005B0000005B0000 + 005B0000005A0000002800000002000000000000000000000000000000000000 + 0000000000000000000000000046FBFBFBFEFFFFFFFFFFFFFFFFFFFFFFFFFDFC + FAFFEBEAE6FF797A79CE00000047000000040000000000000000000000000000 + 0000000000000000000000000048FFFFFFFFF9F9F9FFFBFBFBFFFCFCFCFFFEFE + FEFFEAEBEAFFF3F3F3FF727373D00000004E0000000200000000000000140000 + 005D00000062000000620000008EFFFFFFFFF8F8F8FFFAFAFAFFFCFCFCFFFDFD + FDFFE7E8E7FFFEFEFEFFF3F3F3FF6C6D6CCB00000034000000000000004BFBFB + FBFEFFFFFFFFFFFFFFFFB7B7B7FFFFFFFFFFF7F7F7FFFAFAFAFFFBFBFBFFFDFD + FDFFE4E4E4FFFEFEFEFFFEFEFEFFF3F4F4FF6F6F6FB9000000140000004DFFFF + FFFFFAFAFAFFFCFCFCFFB5B5B5FFFFFFFFFFF6F6F5FFF9F9F9FFFBFBFBFFFCFC + FCFFF8F8F8FFE4E4E4FFE9EAEAFFF3F3F3FFF4F3F1FE000000460000004DFFFF + FFFFFAFAFAFFFBFBFBFFB5B5B5FFFFFFFFFFF4F4F4FFF7F7F7FFFAFAFAFFFBFB + FBFFFCFCFCFFFCFCFCFFFDFDFDFFFDFDFDFFFFFFFFFF0000004A0000004DFFFF + FFFFF9F9F9FFFBFBFBFFB5B5B5FFFFFFFFFFF2F2F2FFF5F5F5FFF8F8F8FFFAFA + FAFFFBFBFBFFFBFBFBFFFCFCFCFFFCFCFCFFFFFFFFFF0000004A0000004DFFFF + FFFFF7F7F7FFFAFAFAFFB4B4B4FFFFFFFFFFF0F0F0FFF3F3F3FFF6F6F5FFF8F8 + F8FFF9F9F9FFFAFAFAFFFAFAFAFFFAFAFAFFFFFFFFFF0000004A0000004DFFFF + FFFFF5F5F5FFF8F8F8FFB3B3B3FFFFFFFFFFEEEEEEFFF1F1F0FFF3F3F3FFF5F5 + F5FFF6F6F6FFF8F8F7FFF8F8F8FFF8F8F8FFFFFFFFFF0000004A0000004DFFFF + FFFFF3F3F3FFF5F5F5FFB2B2B1FFFFFFFFFFECECEBFFEEEEEEFFF0F0F0FFF2F2 + F2FFF4F4F3FFF5F5F4FFF5F5F5FFF5F5F5FFFFFFFFFF0000004A0000004DFFFF + FFFFF0F0F0FFF3F3F2FFB1B1B1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000480000004DFFFF + FFFFEEEEEDFFF0F0EFFFE2E2E2FFB0B0B0FFB0B0B0FFB1B1B0FFB1B1B1FFB1B1 + B1FFB8B8B8FF00000080000000470000004700000046000000100000004DFFFF + FFFFEBEBEAFFEDEDECFFEEEEEEFFF0F0EFFFF1F1F0FFF2F2F1FFF2F2F2FFF2F2 + F2FFFFFFFFFF0000004E000000000000000000000000000000000000004CFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF0000004D00000000000000000000000000000000000000120000 + 004B0000004C0000004C0000004C0000004C0000004C0000004C0000004C0000 + 004C0000004B0000001200000000000000000000000000000000 + } + GroupIndex = 1 + end + end + object btCropDuplicate: TSpeedButton + Left = 172 + Height = 22 + Hint = 'Duplicate this Area' + Top = 20 + Width = 23 + Flat = True + Glyph.Data = { + 36040000424D3604000000000000360000002800000010000000100000000100 + 2000000000000004000000000000000000000000000000000000000000000000 + 0000000000000000000000000012000000570000005B0000005B0000005B0000 + 005B0000005A0000002800000002000000000000000000000000000000000000 + 0000000000000000000000000046FBFBFBFEFFFFFFFFFFFFFFFFFFFFFFFFFDFC + FAFFEBEAE6FF797A79CE00000047000000040000000000000000000000000000 + 0000000000000000000000000048FFFFFFFFF9F9F9FFFBFBFBFFFCFCFCFFFEFE + FEFFEAEBEAFFF3F3F3FF727373D00000004E0000000200000000000000140000 + 005D00000062000000620000008EFFFFFFFFF8F8F8FFFAFAFAFFFCFCFCFFFDFD + FDFFE7E8E7FFFEFEFEFFF3F3F3FF6C6D6CCB00000034000000000000004BFBFB + FBFEFFFFFFFFFFFFFFFFB7B7B7FFFFFFFFFFF7F7F7FFFAFAFAFFFBFBFBFFFDFD + FDFFE4E4E4FFFEFEFEFFFEFEFEFFF3F4F4FF6F6F6FB9000000140000004DFFFF + FFFFFAFAFAFFFCFCFCFFB5B5B5FFFFFFFFFFF6F6F5FFF9F9F9FFFBFBFBFFFCFC + FCFFF8F8F8FFE4E4E4FFE9EAEAFFF3F3F3FFF4F3F1FE000000460000004DFFFF + FFFFFAFAFAFFFBFBFBFFB5B5B5FFFFFFFFFFF4F4F4FFF7F7F7FFFAFAFAFFFBFB + FBFFFCFCFCFFFCFCFCFFFDFDFDFFFDFDFDFFFFFFFFFF0000004A0000004DFFFF + FFFFF9F9F9FFFBFBFBFFB5B5B5FFFFFFFFFFF2F2F2FFF5F5F5FFF8F8F8FFFAFA + FAFFFBFBFBFFFBFBFBFFFCFCFCFFFCFCFCFFFFFFFFFF0000004A0000004DFFFF + FFFFF7F7F7FFFAFAFAFFB4B4B4FFFFFFFFFFF0F0F0FFF3F3F3FFF6F6F5FFF8F8 + F8FFF9F9F9FFFAFAFAFFFAFAFAFFFAFAFAFFFFFFFFFF0000004A0000004DFFFF + FFFFF5F5F5FFF8F8F8FFB3B3B3FFFFFFFFFFEEEEEEFFF1F1F0FFF3F3F3FFF5F5 + F5FFF6F6F6FFF8F8F7FFF8F8F8FFF8F8F8FFFFFFFFFF0000004A0000004DFFFF + FFFFF3F3F3FFF5F5F5FFB2B2B1FFFFFFFFFFECECEBFFEEEEEEFFF0F0F0FFF2F2 + F2FFF4F4F3FFF5F5F4FFF5F5F5FFF5F5F5FFFFFFFFFF0000004A0000004DFFFF + FFFFF0F0F0FFF3F3F2FFB1B1B1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000480000004DFFFF + FFFFEEEEEDFFF0F0EFFFE2E2E2FFB0B0B0FFB0B0B0FFB1B1B0FFB1B1B1FFB1B1 + B1FFB8B8B8FF00000080000000470000004700000046000000100000004DFFFF + FFFFEBEBEAFFEDEDECFFEEEEEEFFF0F0EFFFF1F1F0FFF2F2F1FFF2F2F2FFF2F2 + F2FFFFFFFFFF0000004E000000000000000000000000000000000000004CFFFF + FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + FFFFFFFFFFFF0000004D00000000000000000000000000000000000000120000 + 004B0000004C0000004C0000004C0000004C0000004C0000004C0000004C0000 + 004C0000004B0000001200000000000000000000000000000000 + } + OnClick = btCropDuplicateClick end end object OpenPictureDialog: TOpenPictureDialog @@ -2661,6 +3178,7 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo end object SavePictureDialog: TSavePictureDialog Title = 'Save image as' + DefaultExt = '.jpg' Left = 312 Top = 16 end @@ -2669,12 +3187,16 @@ object FormBGRAImageManipulationDemo: TFormBGRAImageManipulationDemo Top = 74 end object SaveCropList: TSaveDialog - Filter = 'All Files (*.*)|*.*|Crop List File (*.clf)|*.clf' + DefaultExt = '.clf' + Filter = 'Crop List File (*.clf)|*.clf|All Files (*.*)|*.*' + FilterIndex = 0 Left = 191 Top = 368 end object OpenCropList: TOpenDialog - Filter = 'All Files (*.*)|*.*|Crop List File (*.clf)|*.clf' + DefaultExt = '.clf' + Filter = 'Crop List File (*.clf)|*.clf|All Files (*.*)|*.*' + FilterIndex = 0 Left = 192 Top = 418 end diff --git a/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.pas b/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.pas index ea23b77..a622c8a 100644 --- a/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.pas +++ b/test/test_bgraimagemanipulation/unitbgraimagemanipulationdemo.pas @@ -42,6 +42,7 @@ 2013-10-13 - Massimo Magnano - Add multi crop demo + 2023-08 - Resolution, Save in various formats, Z Order ============================================================================ } @@ -52,9 +53,9 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls, - Buttons, ExtDlgs, ComCtrls, ExtCtrls, Menus, BGRAImageManipulation, - BGRABitmap, BGRABitmapTypes, BCPanel, BCButton, BGRASpeedButton, BCLabel, - BCTrackbarUpdown{, BGRATrackBar}; + Buttons, ExtDlgs, ComCtrls, ExtCtrls, Menus, Spin, + {$IFDEF FPC} FPImage,{$ENDIF} BGRAImageManipulation, + BGRABitmap, BGRABitmapTypes, BCPanel, BCButton, BGRASpeedButton, BCLabel, Laz2_XMLCfg; type @@ -68,12 +69,19 @@ TFormBGRAImageManipulationDemo = class(TForm) BCLabel4: TBCLabel; BCLabel5: TBCLabel; BCLabel6: TBCLabel; + BCLabel7: TBCLabel; BCPanelCropAreaLoad: TBCPanel; BCPanelCropArea: TBCPanel; BCPanelCropAreas: TBCPanel; btApplyAspectRatio: TSpeedButton; btBox_Add: TBGRASpeedButton; btBox_Del: TBGRASpeedButton; + btCFlipHLeft: TSpeedButton; + btCFlipHRight: TSpeedButton; + btCFlipVUp: TSpeedButton; + btCFlipVDown: TSpeedButton; + btCropDuplicate: TSpeedButton; + btnEmptyImage: TBCButton; btnLoadCropList: TBCButton; btnSaveCropList: TBCButton; btnSavePictureAll: TBCButton; @@ -85,17 +93,24 @@ TFormBGRAImageManipulationDemo = class(TForm) btnSetAspectRatio: TBCButton; btnRotateLeft: TBCButton; btnRotateRight: TBCButton; + btCRotateRight: TSpeedButton; + btCRotateLeft: TSpeedButton; cbBoxList: TComboBox; chkFullSize: TCheckBox; + cbSaveFormat: TComboBox; edAspectPersonal: TEdit; edAspectRatio: TEdit; - edHeight: TBCTrackbarUpdown; - edLeft: TBCTrackbarUpdown; + edHeight: TFloatSpinEdit; + edLeft: TFloatSpinEdit; edName: TEdit; - edTop: TBCTrackbarUpdown; + edTop: TFloatSpinEdit; edUnit_Type: TComboBox; - edWidth: TBCTrackbarUpdown; + edWidth: TFloatSpinEdit; KeepAspectRatio: TCheckBox; + Label1: TLabel; + Label2: TLabel; + Label3: TLabel; + lbResolution: TLabel; lbAspectRatio: TLabel; lbOptions: TLabel; lbCompression: TLabel; @@ -108,6 +123,19 @@ TFormBGRAImageManipulationDemo = class(TForm) RateCompression: TTrackBar; SelectDirectoryDialog1: TSelectDirectoryDialog; SpeedButton1: TSpeedButton; + btZFront: TSpeedButton; + btZBack: TSpeedButton; + btZDown: TSpeedButton; + btZUp: TSpeedButton; + btCropDuplicateOp: TSpeedButton; + procedure btCFlipHLeftClick(Sender: TObject); + procedure btCFlipHRightClick(Sender: TObject); + procedure btCFlipVDownClick(Sender: TObject); + procedure btCFlipVUpClick(Sender: TObject); + procedure btCropDuplicateClick(Sender: TObject); + procedure btCRotateLeftClick(Sender: TObject); + procedure btCRotateRightClick(Sender: TObject); + procedure btnEmptyImageClick(Sender: TObject); procedure btnGetAspectRatioFromImageClick(Sender: TObject); procedure btnLoadCropListClick(Sender: TObject); procedure btnOpenPictureClick(Sender: TObject); @@ -117,7 +145,12 @@ TFormBGRAImageManipulationDemo = class(TForm) procedure btnSavePictureAllClick(Sender: TObject); procedure btnSavePictureClick(Sender: TObject); procedure btnSetAspectRatioClick(Sender: TObject); + procedure btZBackClick(Sender: TObject); + procedure btZDownClick(Sender: TObject); + procedure btZFrontClick(Sender: TObject); + procedure btZUpClick(Sender: TObject); procedure edNameChange(Sender: TObject); + procedure edUnit_TypeChange(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure KeepAspectRatioClick(Sender: TObject); @@ -132,18 +165,21 @@ TFormBGRAImageManipulationDemo = class(TForm) procedure rgAspectSelectionChanged(Sender: TObject); procedure btApplyAspectRatioClick(Sender: TObject); - procedure AddedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); - procedure DeletedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); - procedure ChangedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); - procedure SelectedChangedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); + procedure AddedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); + procedure DeletedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); + procedure ChangedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); + procedure SelectedChangedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); procedure SpeedButton1Click(Sender: TObject); private { private declarations } lastNewBoxNum :Word; - changingAspect, closing:Boolean; + changingAspect, closing, + inFillBoxUI :Boolean; + function GetCurrentCropArea: TCropArea; procedure FillBoxUI(ABox :TCropArea); procedure SaveCallBack(Bitmap :TBGRABitmap; CropArea: TCropArea); + procedure UpdateBoxList; public { public declarations } end; @@ -160,6 +196,8 @@ implementation procedure TFormBGRAImageManipulationDemo.btnOpenPictureClick(Sender: TObject); var Bitmap: TBGRABitmap; + test:Integer; + begin // To put a new image in the component, you will simply need execute open // picture dialog to locate an image... @@ -171,11 +209,22 @@ procedure TFormBGRAImageManipulationDemo.btnOpenPictureClick(Sender: TObject); // Finally, associate the image into component BGRAImageManipulation.Bitmap := Bitmap; Bitmap.Free; - edLeft.MaxValue:=BGRAImageManipulation.Bitmap.Width; - edTop.MaxValue:=BGRAImageManipulation.Bitmap.Height; - edWidth.MaxValue:=BGRAImageManipulation.Bitmap.Width; - edHeight.MaxValue:=BGRAImageManipulation.Bitmap.Height; - BGRAImageManipulation.addCropArea(Rect(100,100,220,260)); + + lbResolution.Caption:='Resolution : '+#13#10+' '+ + FloatToStr(BGRAImageManipulation.Bitmap.ResolutionX)+' x '+ + FloatToStr(BGRAImageManipulation.Bitmap.ResolutionY)+' '+edUnit_Type.Items[Integer(BGRAImageManipulation.Bitmap.ResolutionUnit)]+#13#10+ + ' '+FloatToStr(BGRAImageManipulation.Bitmap.ResolutionWidth)+' x '+FloatToStr(BGRAImageManipulation.Bitmap.ResolutionHeight)+#13#10+ + ' pixels '+IntToStr(BGRAImageManipulation.Bitmap.Width)+' x '+IntToStr(BGRAImageManipulation.Bitmap.Height); + + if (BGRAImageManipulation.SelectedCropArea=nil) + then begin + edUnit_Type.ItemIndex:=Integer(BGRAImageManipulation.Bitmap.ResolutionUnit); + edLeft.MaxValue:=BGRAImageManipulation.Bitmap.ResolutionWidth; + edTop.MaxValue:=BGRAImageManipulation.Bitmap.ResolutionHeight; + edWidth.MaxValue:=BGRAImageManipulation.Bitmap.ResolutionWidth; + edHeight.MaxValue:=BGRAImageManipulation.Bitmap.ResolutionHeight; + end + else FillBoxUI(BGRAImageManipulation.SelectedCropArea); end; end; @@ -199,6 +248,134 @@ procedure TFormBGRAImageManipulationDemo.btnGetAspectRatioFromImageClick( end; end; +procedure TFormBGRAImageManipulationDemo.btnEmptyImageClick(Sender: TObject); +var + emptyImg :TBGRABitmap; + +begin + try + emptyImg :=TBGRABitmap.Create(0, 0); + BGRAImageManipulation.Bitmap :=emptyImg; + finally + emptyImg.Free; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCRotateLeftClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.RotateLeft; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCFlipVDownClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.FlipVDown; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCFlipHLeftClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.FlipHLeft; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCFlipHRightClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.FlipHRight; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCFlipVUpClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.FlipVUp; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCropDuplicateClick(Sender: TObject); +var + newCropArea :TCropArea; + +begin + if BGRAImageManipulation.SelectedCropArea<>nil then + begin + newCropArea :=TCropArea.Create(BGRAImageManipulation, BGRAImageManipulation.SelectedCropArea, True); + BGRAImageManipulation.SelectedCropArea :=newCropArea; + newCropArea.BorderColor :=VGALime; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btCRotateRightClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + if btCropDuplicateOp.Down then + begin + CropArea :=TCropArea.Create(BGRAImageManipulation, CropArea, True); + BGRAImageManipulation.SelectedCropArea :=CropArea; + end; + CropArea.RotateRight; + end; +end; + procedure TFormBGRAImageManipulationDemo.btnLoadCropListClick(Sender: TObject); begin try @@ -219,45 +396,55 @@ procedure TFormBGRAImageManipulationDemo.btnSaveCropListClick(Sender: TObject); procedure TFormBGRAImageManipulationDemo.btnSavePictureClick(Sender: TObject); var - JpegImage: TJpegImage; -begin - // This example save image compress in JPEG format + curBitmap :TBGRABitmap; - // Execute our Save Picture Dialog - SavePictureDialog.Filter := 'JPEG Image File (*.jpg, *.jpeg)'; +begin if SavePictureDialog.Execute then begin try - // Compress - JpegImage := TJpegImage.Create; if (chkFullSize.Checked) - then JpegImage.Assign(BGRAImageManipulation.getBitmap) - else JpegImage.Assign(BGRAImageManipulation.getResampledBitmap); - JpegImage.CompressionQuality := RateCompression.Position; + then curBitmap :=BGRAImageManipulation.getBitmap + else curBitmap :=BGRAImageManipulation.getResampledBitmap; - // And save to file - JpegImage.SaveToFile(SavePictureDialog.FileName); + curBitmap.SaveToFile(SavePictureDialog.FileName); finally - JpegImage.Free; + curBitmap.Free; end; end; end; procedure TFormBGRAImageManipulationDemo.SaveCallBack(Bitmap :TBGRABitmap; CropArea: TCropArea); var - JpegImage: TJpegImage; + ext:String; + i:Integer; + begin - try - // Compress - JpegImage := TJpegImage.Create; - JpegImage.Assign(Bitmap); - JpegImage.CompressionQuality := RateCompression.Position; + ext:=ImageHandlers.Extensions[cbSaveFormat.Items[cbSaveFormat.ItemIndex]]; + i :=Pos(';', ext); + if (i>0) then ext :=Copy(ext, 1, i-1); + Bitmap.SaveToFile(SelectDirectoryDialog1.FileName+DirectorySeparator+CropArea.Name+'.'+ext); +end; - // And save to file - JpegImage.SaveToFile(SelectDirectoryDialog1.FileName+DirectorySeparator+CropArea.Name+'.jpg'); - finally - JpegImage.Free; - end; +procedure TFormBGRAImageManipulationDemo.UpdateBoxList; +var + i :Integer; + CropArea, + SelArea:TCropArea; + +begin + cbBoxList.OnChange:=nil; + + //SelArea :=BGRAImageManipulation.SelectedCropArea; + cbBoxList.Clear; + for i:=0 to BGRAImageManipulation.CropAreas.Count-1 do + begin + CropArea :=BGRAImageManipulation.CropAreas.items[i]; + cbBoxList.AddItem(CropArea.Name, CropArea); + end; + //BGRAImageManipulation.SelectedCropArea :=SelArea; + cbBoxList.ItemIndex:=cbBoxList.Items.IndexOfObject(BGRAImageManipulation.SelectedCropArea); + + cbBoxList.OnChange:=@cbBoxListChange; end; procedure TFormBGRAImageManipulationDemo.btnSavePictureAllClick(Sender: TObject); @@ -283,13 +470,79 @@ procedure TFormBGRAImageManipulationDemo.btnSetAspectRatioClick(Sender: TObject) end; end; +procedure TFormBGRAImageManipulationDemo.btZBackClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil + then begin + CropArea.BringToBack; + UpdateBoxList; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btZDownClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil + then begin + CropArea.BringBackward; + UpdateBoxList; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btZFrontClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil + then begin + CropArea.BringToFront; + UpdateBoxList; + end; +end; + +procedure TFormBGRAImageManipulationDemo.btZUpClick(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil + then begin + CropArea.BringForward; + UpdateBoxList; + end; +end; + procedure TFormBGRAImageManipulationDemo.edNameChange(Sender: TObject); var CropArea :TCropArea; begin - CropArea :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); - CropArea.Name :=edName.Text; + CropArea :=GetCurrentCropArea; + if CropArea<>nil + then CropArea.Name :=edName.Text; +end; + +procedure TFormBGRAImageManipulationDemo.edUnit_TypeChange(Sender: TObject); +var + CropArea :TCropArea; + +begin + CropArea :=GetCurrentCropArea; + if CropArea<>nil then + begin + CropArea.AreaUnit:=TResolutionUnit(edUnit_Type.ItemIndex); + FillBoxUI(CropArea); + end; end; procedure TFormBGRAImageManipulationDemo.FormCloseQuery(Sender: TObject; @@ -310,7 +563,10 @@ procedure TFormBGRAImageManipulationDemo.btBox_AddClick(Sender: TObject); newCropArea :TCropArea; begin - newCropArea :=BGRAImageManipulation.addCropArea(Rect(50, 50, 100, 100), 0 (*, Integer(newBox)*)); + if edUnit_Type.ItemIndex=0 + then newCropArea :=BGRAImageManipulation.addCropArea(Rect(50, 50, 100, 100)) + else newCropArea :=BGRAImageManipulation.addCropArea(Rect(1, 1, 2, 2), TResolutionUnit(edUnit_Type.ItemIndex)); + newCropArea.BorderColor :=VGALime; end; @@ -321,13 +577,13 @@ procedure TFormBGRAImageManipulationDemo.btBox_DelClick(Sender: TObject); begin curIndex :=cbBoxList.ItemIndex; - CropArea :=TCropArea(cbBoxList.Items.Objects[curIndex]); - BGRAImageManipulation.delCropArea(CropArea); - cbBoxList.Items.Delete(curIndex); -(* if (BGRAImageManipulation.SelectedCropArea <> nil) - then cbBoxList.ItemIndex:=BGRAImageManipulation.SelectedCropArea.Index - else cbBoxList.ItemIndex:=-1; - FillBoxUI(BGRAImageManipulation.SelectedCropArea);*) + if (curIndex>-1) then + begin + CropArea :=TCropArea(cbBoxList.Items.Objects[curIndex]); + BGRAImageManipulation.delCropArea(CropArea); + cbBoxList.ItemIndex:=cbBoxList.Items.IndexOfObject(BGRAImageManipulation.SelectedCropArea); + end; + FillBoxUI(BGRAImageManipulation.SelectedCropArea); end; procedure TFormBGRAImageManipulationDemo.cbBoxListChange(Sender: TObject); @@ -340,12 +596,11 @@ procedure TFormBGRAImageManipulationDemo.edHeightChange(Sender: TObject; AByUser CropArea :TCropArea; begin - if AByUser then - begin - CropArea :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); - if (CropArea<>nil) - then CropArea.Height:=edHeight.Value; - end; + if inFillBoxUI then exit; + + CropArea :=GetCurrentCropArea; + if (CropArea<>nil) + then CropArea.Height:=edHeight.Value; end; procedure TFormBGRAImageManipulationDemo.edLeftChange(Sender: TObject; AByUser: boolean); @@ -353,12 +608,11 @@ procedure TFormBGRAImageManipulationDemo.edLeftChange(Sender: TObject; AByUser: CropArea :TCropArea; begin - if AByUser then - begin - CropArea :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); - if (CropArea<>nil) - then CropArea.Left :=edLeft.Value; - end; + if inFillBoxUI then exit; + + CropArea :=GetCurrentCropArea; + if (CropArea<>nil) + then CropArea.Left :=edLeft.Value; end; procedure TFormBGRAImageManipulationDemo.edTopChange(Sender: TObject; AByUser: boolean); @@ -366,12 +620,11 @@ procedure TFormBGRAImageManipulationDemo.edTopChange(Sender: TObject; AByUser: b CropArea :TCropArea; begin - if AByUser then - begin - CropArea :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); - if (CropArea<>nil) - then CropArea.Top :=edTop.Value; - end; + if inFillBoxUI then exit; + + CropArea :=GetCurrentCropArea; + if (CropArea<>nil) + then CropArea.Top :=edTop.Value; end; procedure TFormBGRAImageManipulationDemo.edWidthChange(Sender: TObject; AByUser: boolean); @@ -379,23 +632,36 @@ procedure TFormBGRAImageManipulationDemo.edWidthChange(Sender: TObject; AByUser: CropArea :TCropArea; begin - if AByUser then - begin - CropArea :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); - if (CropArea<>nil) - then CropArea.Width:=edWidth.Value; - end; + if inFillBoxUI then exit; + + CropArea :=GetCurrentCropArea; + if (CropArea<>nil) + then CropArea.Width:=edWidth.Value; end; procedure TFormBGRAImageManipulationDemo.FormCreate(Sender: TObject); var - i :Integer; + i,j :Integer; + t,e:String; begin closing :=False; changingAspect :=False; + inFillBoxUI :=False; lastNewBoxNum :=0; TStringList(cbBoxList.Items).OwnsObjects:=False; + j:=0; + for i :=0 to ImageHandlers.Count-1 do + begin + t :=ImageHandlers.TypeNames[i]; + e :=ImageHandlers.Extensions[t]; + if (ImageHandlers.ImageWriter[t]<>nil) then + begin + cbSaveFormat.Items.Add(t); + if (Pos('jpg', e)>0) then j:=i; + end; + end; + cbSaveFormat.ItemIndex:=j-1; end; procedure TFormBGRAImageManipulationDemo.rgAspectSelectionChanged(Sender: TObject); @@ -425,7 +691,7 @@ procedure TFormBGRAImageManipulationDemo.btApplyAspectRatioClick(Sender: TObject end; end; -procedure TFormBGRAImageManipulationDemo.AddedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); +procedure TFormBGRAImageManipulationDemo.AddedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); var curIndex :Integer; @@ -437,10 +703,11 @@ procedure TFormBGRAImageManipulationDemo.AddedCrop(AOwner: TBGRAImageManipulatio cbBoxList.AddItem(CropArea.Name, CropArea); cbBoxList.ItemIndex:=cbBoxList.Items.IndexOfObject(CropArea); + //CropArea.AreaUnit:=BGRAImageManipulation.Bitmap.ResolutionUnit; FillBoxUI(CropArea); end; -procedure TFormBGRAImageManipulationDemo.DeletedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); +procedure TFormBGRAImageManipulationDemo.DeletedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); var delIndex :Integer; begin @@ -450,13 +717,14 @@ procedure TFormBGRAImageManipulationDemo.DeletedCrop(AOwner: TBGRAImageManipulat delIndex :=cbBoxList.Items.IndexOfObject(CropArea); if (delIndex<>-1) then cbBoxList.Items.Delete(delIndex); + BCPanelCropArea.Enabled:=(cbBoxList.Items.Count>0); end; except end; //MessageDlg('Deleting Crop Area', 'Deleting '+CropArea.Name, mtInformation, [mbOk], 0); end; -procedure TFormBGRAImageManipulationDemo.ChangedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); +procedure TFormBGRAImageManipulationDemo.ChangedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); begin if (cbBoxList.Items.Objects[cbBoxList.ItemIndex] = CropArea) then begin @@ -468,7 +736,7 @@ procedure TFormBGRAImageManipulationDemo.ChangedCrop(AOwner: TBGRAImageManipulat end; end; -procedure TFormBGRAImageManipulationDemo.SelectedChangedCrop(AOwner: TBGRAImageManipulation; CropArea: TCropArea); +procedure TFormBGRAImageManipulationDemo.SelectedChangedCrop(Sender: TBGRAImageManipulation; CropArea: TCropArea); var newIndex :Integer; begin @@ -482,15 +750,43 @@ procedure TFormBGRAImageManipulationDemo.SelectedChangedCrop(AOwner: TBGRAImageM procedure TFormBGRAImageManipulationDemo.SpeedButton1Click(Sender: TObject); begin - BGRAImageManipulation.tests; + BGRAImageManipulation.SetEmptyImageSizeToCropAreas(False); +end; + +function TFormBGRAImageManipulationDemo.GetCurrentCropArea: TCropArea; +begin + if (cbBoxList.ItemIndex<0) + then Result :=nil + else Result :=TCropArea(cbBoxList.Items.Objects[cbBoxList.ItemIndex]); end; procedure TFormBGRAImageManipulationDemo.FillBoxUI(ABox: TCropArea); begin if (ABox<>nil) then begin + inFillBoxUI :=True; BCPanelCropArea.Enabled :=True; edName.Text :=ABox.Name; + edUnit_Type.ItemIndex :=Integer(ABox.AreaUnit); + + if (ABox.AreaUnit=ruNone) + then begin + edLeft.DecimalPlaces:=0; + edTop.DecimalPlaces:=0; + edWidth.DecimalPlaces:=0; + edHeight.DecimalPlaces:=0; + end + else begin + edLeft.DecimalPlaces:=3; + edTop.DecimalPlaces:=3; + edWidth.DecimalPlaces:=3; + edHeight.DecimalPlaces:=3; + end; + edLeft.MaxValue:=ABox.MaxWidth; + edTop.MaxValue:=ABox.MaxHeight; + edWidth.MaxValue:=edLeft.MaxValue; + edHeight.MaxValue:=edTop.MaxValue; + edLeft.Value :=ABox.Left; edTop.Value :=ABox.Top; edWidth.Value :=ABox.Width; @@ -505,8 +801,7 @@ procedure TFormBGRAImageManipulationDemo.FillBoxUI(ABox: TCropArea); end; edAspectPersonal.Text:=ABox.AspectRatio; changingAspect:=False; - - //edUnit_Type.ItemIndex :=Integer(ABox^.UnitType); + inFillBoxUI :=False; end else BCPanelCropArea.Enabled :=False; end; diff --git a/test/test_checklistbox/project1.ico b/test/test_checklistbox/project1.ico new file mode 100644 index 0000000..10c5fc1 Binary files /dev/null and b/test/test_checklistbox/project1.ico differ diff --git a/test/test_checklistbox/project1.lpi b/test/test_checklistbox/project1.lpi new file mode 100644 index 0000000..e4edf54 --- /dev/null +++ b/test/test_checklistbox/project1.lpi @@ -0,0 +1,80 @@ + + + + + + + + + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + <Icon Value="0"/> + </General> + <BuildModes> + <Item Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages> + <Item> + <PackageName Value="bgracontrols"/> + </Item> + <Item> + <PackageName Value="LCL"/> + </Item> + </RequiredPackages> + <Units> + <Unit> + <Filename Value="project1.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="unit1.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="Form1"/> + <ResourceBaseClass Value="Form"/> + <UnitName Value="Unit1"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="project1"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/test/test_checklistbox/project1.lpr b/test/test_checklistbox/project1.lpr new file mode 100644 index 0000000..ac2bb7a --- /dev/null +++ b/test/test_checklistbox/project1.lpr @@ -0,0 +1,25 @@ +program project1; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + {$IFDEF HASAMIGA} + athreads, + {$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, Unit1 + { you can add units after this }; + +{$R *.res} + +begin + RequireDerivedFormResource:=True; + Application.Scaled:=True; + Application.Initialize; + Application.CreateForm(TForm1, Form1); + Application.Run; +end. + diff --git a/test/test_checklistbox/unit1.lfm b/test/test_checklistbox/unit1.lfm new file mode 100644 index 0000000..f3813e3 --- /dev/null +++ b/test/test_checklistbox/unit1.lfm @@ -0,0 +1,30 @@ +object Form1: TForm1 + Left = 285 + Height = 240 + Top = 31 + Width = 320 + Caption = 'Form1' + ClientHeight = 240 + ClientWidth = 320 + OnCreate = FormCreate + LCLVersion = '2.2.6.0' + object CheckListBox1: TCheckListBox + Left = 48 + Height = 174 + Top = 32 + Width = 198 + ItemHeight = 32 + OnDrawItem = CheckListBox1DrawItem + Style = lbOwnerDrawFixed + TabOrder = 0 + end + object BGRAThemeCheckBox1: TBGRAThemeCheckBox + Left = 48 + Height = 19 + Top = 8 + Width = 165 + Caption = 'BGRAThemeCheckBox1' + Checked = False + TabOrder = 1 + end +end diff --git a/test/test_checklistbox/unit1.pas b/test/test_checklistbox/unit1.pas new file mode 100644 index 0000000..76cfb22 --- /dev/null +++ b/test/test_checklistbox/unit1.pas @@ -0,0 +1,125 @@ +unit Unit1; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Graphics, Dialogs, CheckLst, Types, + StdCtrls, BGRAThemeCheckBox, BGRABitmap, BGRABitmapTypes, BGRATheme; + +type + + { TForm1 } + + TForm1 = class(TForm) + BGRAThemeCheckBox1: TBGRAThemeCheckBox; + CheckListBox1: TCheckListBox; + procedure CheckListBox1DrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); + procedure FormCreate(Sender: TObject); + private + procedure DrawCheckBox(aCaption: string; State: TBGRAThemeButtonState; + aFocused: boolean; Checked: boolean; ARect: TRect; + ASurface: TBGRAThemeSurface); + + public + + end; + +var + Form1: TForm1; + +implementation + +{$R *.lfm} + +{ TForm1 } + +procedure TForm1.CheckListBox1DrawItem(Control: TWinControl; Index: Integer; + ARect: TRect; State: TOwnerDrawState); +var + surface: TBGRAThemeSurface; + parentForm: TCustomForm; + lclDPI: Integer; +begin + parentForm := GetParentForm(Control, False); + if Assigned(parentForm) then + lclDPI := parentForm.PixelsPerInch + else lclDPI := Screen.PixelsPerInch; + surface := TBGRAThemeSurface.Create(ARect, TCheckListBox(Control).Canvas, Control.GetCanvasScaleFactor, lclDPI); + try + DrawCheckBox(TCheckListBox(Control).Items[Index], btbsNormal, False, TCheckListBox(Control).Checked[Index], ARect, surface); + finally + surface.Free; + end; +end; + +procedure TForm1.FormCreate(Sender: TObject); +begin + CheckListBox1.AddItem('Red', nil); + CheckListBox1.AddItem('Green', nil); + CheckListBox1.AddItem('Blue', nil); + CheckListBox1.AddItem('Alpha', nil); +end; + +procedure TForm1.DrawCheckBox(aCaption: string; State: TBGRAThemeButtonState; + aFocused: boolean; Checked: boolean; ARect: TRect; ASurface: TBGRAThemeSurface + ); +var + Style: TTextStyle; + aColor: TBGRAPixel; + aleft, atop, aright, abottom: integer; + penWidth: single; +begin + with ASurface do + begin + DestCanvas.Font.Color := clBlack; + case State of + btbsHover: aColor := BGRA(0, 120, 215); + btbsActive: aColor := BGRA(0, 84, 153); + btbsDisabled: + begin + DestCanvas.Font.Color := clGray; + aColor := BGRA(204, 204, 204); + end; + else {btbsNormal} + aColor := BGRABlack; + end; + + Bitmap.Fill(BGRAWhite); + BitmapRect := ARect; + penWidth := ASurface.ScaleForBitmap(10) / 10; + aleft := round(penWidth); + aright := Bitmap.Height-round(penWidth); + atop := round(penWidth); + abottom := Bitmap.Height-round(penWidth); + Bitmap.RectangleAntialias(aleft-0.5+penWidth/2, atop-0.5+penWidth/2, + aright-0.5-penWidth/2, abottom-0.5-penWidth/2, + aColor, penWidth); + aleft := round(penWidth*2); + aright := Bitmap.Height-round(penWidth*2); + atop := round(penWidth*2); + abottom := Bitmap.Height-round(penWidth*2); + if Checked then + Bitmap.DrawPolyLineAntialias(Bitmap.ComputeBezierSpline( + [BezierCurve(pointF(aleft + 2, atop + 3), PointF((aleft + aright - 1) / 2, abottom - 3)), + BezierCurve(PointF((aleft + aright - 1) / 2, abottom - 3), PointF( + (aleft + aright - 1) / 2, (atop * 2 + abottom - 1) / 3), PointF(aright - 2, atop))]), + Color, penWidth*1.5); + DrawBitmap; + + if aCaption <> '' then + begin + fillchar(Style, sizeof(Style), 0); + Style.Alignment := taLeftJustify; + Style.Layout := tlCenter; + Style.Wordbreak := True; + DestCanvas.TextRect(ARect, + ARect.Height, 0, aCaption, Style); + end; + end; +end; + +end. + diff --git a/test/test_windows_theme/umain.lfm b/test/test_windows_theme/umain.lfm new file mode 100644 index 0000000..2c3e30e --- /dev/null +++ b/test/test_windows_theme/umain.lfm @@ -0,0 +1,123 @@ +object frmWindowsTheme: TfrmWindowsTheme + Left = 63 + Height = 480 + Top = 225 + Width = 848 + Caption = 'Windows Theme' + ClientHeight = 480 + ClientWidth = 848 + Color = 15987699 + DesignTimePPI = 192 + Position = poScreenCenter + LCLVersion = '3.99.0.0' + OnCreate = FormCreate + object BCPanel1: TBCPanel + Left = 16 + Height = 224 + Top = 16 + Width = 816 + Anchors = [akTop, akLeft, akRight] + Background.Color = 16514043 + Background.Gradient1.StartColor = clWhite + Background.Gradient1.EndColor = clBlack + Background.Gradient1.GradientType = gtLinear + Background.Gradient1.Point1XPercent = 0 + Background.Gradient1.Point1YPercent = 0 + Background.Gradient1.Point2XPercent = 0 + Background.Gradient1.Point2YPercent = 100 + Background.Gradient2.StartColor = clWhite + Background.Gradient2.EndColor = clBlack + Background.Gradient2.GradientType = gtLinear + Background.Gradient2.Point1XPercent = 0 + Background.Gradient2.Point1YPercent = 0 + Background.Gradient2.Point2XPercent = 0 + Background.Gradient2.Point2YPercent = 100 + Background.Gradient1EndPercent = 35 + Background.Style = bbsColor + BevelInner = bvNone + BevelOuter = bvNone + BevelWidth = 1 + Border.Color = 15066597 + Border.Style = bboSolid + BorderBCStyle = bpsBorder + FontEx.Color = clDefault + FontEx.FontQuality = fqSystemClearType + FontEx.Shadow = False + FontEx.ShadowRadius = 5 + FontEx.ShadowOffsetX = 5 + FontEx.ShadowOffsetY = 5 + FontEx.Style = [] + ParentBackground = False + Rounding.RoundX = 5 + Rounding.RoundY = 5 + TabOrder = 0 + object BCLabel1: TBCLabel + Left = 48 + Height = 28 + Top = 48 + Width = 267 + Background.Gradient1.StartColor = clWhite + Background.Gradient1.EndColor = clBlack + Background.Gradient1.GradientType = gtLinear + Background.Gradient1.Point1XPercent = 0 + Background.Gradient1.Point1YPercent = 0 + Background.Gradient1.Point2XPercent = 0 + Background.Gradient1.Point2YPercent = 100 + Background.Gradient2.StartColor = clWhite + Background.Gradient2.EndColor = clBlack + Background.Gradient2.GradientType = gtLinear + Background.Gradient2.Point1XPercent = 0 + Background.Gradient2.Point1YPercent = 0 + Background.Gradient2.Point2XPercent = 0 + Background.Gradient2.Point2YPercent = 100 + Background.Gradient1EndPercent = 35 + Background.Style = bbsClear + Border.Style = bboNone + Caption = 'ConfiguraciĆ³n recomendada' + FontEx.Color = 1776411 + FontEx.FontQuality = fqSystemClearType + FontEx.Height = 20 + FontEx.Shadow = False + FontEx.ShadowRadius = 5 + FontEx.ShadowOffsetX = 5 + FontEx.ShadowOffsetY = 5 + FontEx.Style = [fsBold] + Rounding.RoundX = 1 + Rounding.RoundY = 1 + end + object BCLabel2: TBCLabel + Left = 48 + Height = 19 + Top = 128 + Width = 280 + Background.Gradient1.StartColor = clWhite + Background.Gradient1.EndColor = clBlack + Background.Gradient1.GradientType = gtLinear + Background.Gradient1.Point1XPercent = 0 + Background.Gradient1.Point1YPercent = 0 + Background.Gradient1.Point2XPercent = 0 + Background.Gradient1.Point2YPercent = 100 + Background.Gradient2.StartColor = clWhite + Background.Gradient2.EndColor = clBlack + Background.Gradient2.GradientType = gtLinear + Background.Gradient2.Point1XPercent = 0 + Background.Gradient2.Point1YPercent = 0 + Background.Gradient2.Point2XPercent = 0 + Background.Gradient2.Point2YPercent = 100 + Background.Gradient1EndPercent = 35 + Background.Style = bbsClear + Border.Style = bboNone + Caption = 'ConfiguraciĆ³n reciente y usada habitualmente' + FontEx.Color = 6250335 + FontEx.FontQuality = fqSystemClearType + FontEx.Height = 14 + FontEx.Shadow = False + FontEx.ShadowRadius = 5 + FontEx.ShadowOffsetX = 5 + FontEx.ShadowOffsetY = 5 + FontEx.Style = [] + Rounding.RoundX = 1 + Rounding.RoundY = 1 + end + end +end diff --git a/test/test_windows_theme/umain.pas b/test/test_windows_theme/umain.pas new file mode 100644 index 0000000..b4aeb53 --- /dev/null +++ b/test/test_windows_theme/umain.pas @@ -0,0 +1,42 @@ +unit umain; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, Forms, Controls, Graphics, Dialogs, BCPanel, BCLabel; + +type + + { TfrmWindowsTheme } + + TfrmWindowsTheme = class(TForm) + BCLabel1: TBCLabel; + BCLabel2: TBCLabel; + BCPanel1: TBCPanel; + procedure FormCreate(Sender: TObject); + private + + public + + end; + +var + frmWindowsTheme: TfrmWindowsTheme; + +implementation + +{$R *.lfm} + +{ TfrmWindowsTheme } + +procedure TfrmWindowsTheme.FormCreate(Sender: TObject); +begin + BCLabel1.FontEx.Height := ScaleY(BCLabel1.FontEx.Height, 96); + BCLabel2.FontEx.Height := ScaleY(BCLabel2.FontEx.Height, 96); + BCPanel1.Border.Width := ScaleY(BCPanel1.Border.Width, 96); +end; + +end. + diff --git a/test/test_windows_theme/windowstheme.ico b/test/test_windows_theme/windowstheme.ico new file mode 100644 index 0000000..10c5fc1 Binary files /dev/null and b/test/test_windows_theme/windowstheme.ico differ diff --git a/test/test_windows_theme/windowstheme.lpi b/test/test_windows_theme/windowstheme.lpi new file mode 100644 index 0000000..596df4a --- /dev/null +++ b/test/test_windows_theme/windowstheme.lpi @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8"?> +<CONFIG> + <ProjectOptions> + <Version Value="12"/> + <PathDelim Value="\"/> + <General> + <SessionStorage Value="InProjectDir"/> + <Title Value="windowstheme"/> + <Scaled Value="True"/> + <ResourceType Value="res"/> + <UseXPManifest Value="True"/> + <XPManifest> + <DpiAware Value="True"/> + </XPManifest> + </General> + <BuildModes> + <Item Name="Debug" Default="True"/> + <Item Name="Release"> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="windowstheme"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <CodeGeneration> + <SmartLinkUnit Value="True"/> + <Optimizations> + <OptimizationLevel Value="3"/> + </Optimizations> + </CodeGeneration> + <Linking> + <Debugging> + <GenerateDebugInfo Value="False"/> + <RunWithoutDebug Value="True"/> + </Debugging> + <LinkSmart Value="True"/> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <ConfigFile> + <WriteConfigFilePath Value=""/> + </ConfigFile> + </Other> + </CompilerOptions> + </Item> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <RequiredPackages> + <Item> + <PackageName Value="bgracontrols"/> + </Item> + <Item> + <PackageName Value="LCL"/> + </Item> + </RequiredPackages> + <Units> + <Unit> + <Filename Value="windowstheme.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="umain.pas"/> + <IsPartOfProject Value="True"/> + <ComponentName Value="frmWindowsTheme"/> + <HasResources Value="True"/> + <ResourceBaseClass Value="Form"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="windowstheme"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <Checks> + <IOChecks Value="True"/> + <RangeChecks Value="True"/> + <OverflowChecks Value="True"/> + <StackChecks Value="True"/> + </Checks> + <VerifyObjMethodCallValidity Value="True"/> + </CodeGeneration> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + <UseHeaptrc Value="True"/> + <TrashVariables Value="True"/> + <UseExternalDbgSyms Value="True"/> + </Debugging> + <Options> + <Win32> + <GraphicApplication Value="True"/> + </Win32> + </Options> + </Linking> + <Other> + <ConfigFile> + <WriteConfigFilePath Value=""/> + </ConfigFile> + </Other> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/test/test_windows_theme/windowstheme.lpr b/test/test_windows_theme/windowstheme.lpr new file mode 100644 index 0000000..a9f43ae --- /dev/null +++ b/test/test_windows_theme/windowstheme.lpr @@ -0,0 +1,25 @@ +program windowstheme; + +{$mode objfpc}{$H+} + +uses + {$IFDEF UNIX} + cthreads, + {$ENDIF} + {$IFDEF HASAMIGA} + athreads, + {$ENDIF} + Interfaces, // this includes the LCL widgetset + Forms, umain + { you can add units after this }; + +{$R *.res} + +begin + RequireDerivedFormResource:=True; + Application.Scaled:=True; + Application.Initialize; + Application.CreateForm(TfrmWindowsTheme, frmWindowsTheme); + Application.Run; +end. +