diff --git a/Examples/form.simba b/Examples/form.simba index 9a2700623..d67f75b7e 100644 --- a/Examples/form.simba +++ b/Examples/form.simba @@ -38,6 +38,8 @@ var List: TLazListBox; Lbl: TLazLabel; Panel: TLazPanel; + Img: TLazImage; + SimbaImg: TImage; begin Form := TLazForm.Create(); Form.SetCaption('Example form'); @@ -49,6 +51,16 @@ begin Form.SetColor(Colors.DARK_GREY); Form.SetBorderStyle(bsSingle); // Do not allow resizing + SimbaImg := TImage.CreateFromTarget([0,0,400,400]); + + Img := TLazImage.Create(Form); + Img.SetParent(Form); + Img.SetBounds(400,200,200,200); + Img.SetStretch(True); + Img.GetPicture().SetBitmap(SimbaImg.ToLazBitmap()); + + SimbaImg.Free(); + Button := TLazButton.Create(Form); Button.SetParent(Form); Button.SetAutoSize(True); diff --git a/Examples/image_drawtext.simba b/Examples/image_drawtext.simba new file mode 100644 index 000000000..4b3c1e6a9 --- /dev/null +++ b/Examples/image_drawtext.simba @@ -0,0 +1,23 @@ +var + myImage: TImage; + myBox: TBox; +begin + myImage := TImage.Create(500,1000); + myImage.Fill(Colors.DARK_GRAY); + + myImage.SetFontAntialiasing(True); + myImage.SetFontSize(20); + + myImage.DrawTextLines(TImage.FontNames, [10,10], Colors.BLACK); + + myBox := [225,25,450,240]; + myImage.DrawBox(myBox, Colors.RED); + myImage.DrawText(FormatDateTime('c', Now()), myBox, [ETextDrawAlignment.CENTER, ETextDrawAlignment.VERTICAL_CENTER], Colors.BLACK); + + myImage.SetFontBold(True); + myImage.SetFontSize(50); + myImage.DrawText(IntToStr(Random(10000)), [225, 300], Colors.NAVY); + + myImage.Show(); + myImage.Free(); +end. diff --git a/Source/Simba.lpi b/Source/Simba.lpi index 3010a6ce6..2212305e9 100644 --- a/Source/Simba.lpi +++ b/Source/Simba.lpi @@ -17,7 +17,7 @@ - + @@ -29,6 +29,7 @@ + diff --git a/Source/Simba.res b/Source/Simba.res index cdc30e75f..38407db4b 100644 Binary files a/Source/Simba.res and b/Source/Simba.res differ diff --git a/Source/forms/simba.openexampleform.pas b/Source/forms/simba.openexampleform.pas index b6e3b3aa5..b0517b216 100644 --- a/Source/forms/simba.openexampleform.pas +++ b/Source/forms/simba.openexampleform.pas @@ -207,6 +207,7 @@ procedure TSimbaOpenExampleForm.FormCreate(Sender: TObject); AddNode('JSON', 'EXAMPLE_JSON' ); AddNode('Form', 'EXAMPLE_FORM' ); AddNode('IRC', 'EXAMPLE_IRC' ); + AddNode('Draw Text', 'EXAMPLE_DRAWTEXT' ); end; procedure TSimbaOpenExampleForm.DoTreeViewSelectionChanged(Sender: TObject); diff --git a/Source/image/simba.image.pas b/Source/image/simba.image.pas index b20d08516..22430c20d 100644 --- a/Source/image/simba.image.pas +++ b/Source/image/simba.image.pas @@ -39,6 +39,7 @@ TSimbaImage = class(TSimbaBaseClass) FTextDrawer: TSimbaTextDrawer; + procedure RaiseOutOfImageException(X, Y: Integer); procedure NotifyUnfreed; override; procedure _DrawTPA(TPA: TPointArray; Color: TColor); @@ -82,7 +83,7 @@ TSimbaImage = class(TSimbaBaseClass) public class var SaveUnfreedImages: ShortString; class function LoadFonts(Dir: String): Boolean; - class function LoadedFontNames: TStringArray; + class function FontNames: TStringArray; public DefaultPixel: TColorBGRA; @@ -96,8 +97,8 @@ TSimbaImage = class(TSimbaBaseClass) destructor Destroy; override; - property Data: PColorBGRA read FData write FData; - property DataOwner: Boolean read FDataOwner write FDataOwner; + property Data: PColorBGRA read FData; + property DataOwner: Boolean read FDataOwner; property DataSize: SizeUInt read FDataSize; property LineStarts: TSimbaImageLineStarts read FLineStarts; @@ -116,8 +117,7 @@ TSimbaImage = class(TSimbaBaseClass) property FontBold: Boolean read GetFontBold write SetFontBold; property FontItalic: Boolean read GetFontItalic write SetFontItalic; - function InImage(const X, Y: Integer): Boolean; inline; - procedure AssertInImage(const Method: String; const X, Y: Integer); + function InImage(const X, Y: Integer): Boolean; function Equals(Other: TObject): Boolean; override; function Equals(Other: TSimbaImage): Boolean; overload; @@ -127,7 +127,7 @@ TSimbaImage = class(TSimbaBaseClass) function TextSize(Text: String): TPoint; procedure DrawText(Text: String; Position: TPoint; Color: TColor); overload; - procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); overload; + procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); overload; procedure DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor); procedure SetSize(NewWidth, NewHeight: Integer); @@ -204,6 +204,7 @@ TSimbaImage = class(TSimbaBaseClass) procedure Clear(Box: TBox); overload; procedure ClearInverted(Box: TBox); + procedure SplitChannels(out B,G,R,A: TByteArray); function GetColors: TColorArray; procedure ReplaceColor(OldColor, NewColor: TColor); procedure ReplaceColors(OldColors, NewColors: TColorArray); @@ -226,7 +227,7 @@ TSimbaImage = class(TSimbaBaseClass) procedure Pad(Amount: Integer); function ToLazBitmap: TBitmap; - procedure LoadFromLazBitmap(LazBitmap: TBitmap); + procedure FromLazBitmap(LazBitmap: TBitmap); function ToGreyMatrix: TByteMatrix; function ToMatrix: TIntegerMatrix; overload; @@ -235,15 +236,14 @@ TSimbaImage = class(TSimbaBaseClass) function ThresholdAdaptive(Alpha, Beta: Byte; AInvert: Boolean; Method: ESimbaImageThreshMethod; K: Integer): TSimbaImage; function ThresholdSauvola(Radius: Integer; AInvert: Boolean = False; R: Single = 128; K: Single = 0.5): TSimbaImage; - function SaveToFile(FileName: String; OverwriteIfExists: Boolean = False): Boolean; + procedure Load(FileName: String); overload; + procedure Load(FileName: String; Area: TBox); overload; + function Save(FileName: String; OverwriteIfExists: Boolean = False): Boolean; function SaveToString: String; - procedure LoadFromStream(Stream: TStream; FileName: String); - procedure LoadFromFile(FileName: String); overload; - procedure LoadFromFile(FileName: String; Area: TBox); overload; - procedure LoadFromString(Str: String); - procedure LoadFromData(AWidth, AHeight: Integer; AData: PColorBGRA; ADataWidth: Integer); - procedure LoadFromImage(Image: TSimbaImage); + procedure FromStream(Stream: TStream; FileName: String); + procedure FromString(Str: String); + procedure FromData(AWidth, AHeight: Integer; AData: PColorBGRA; ADataWidth: Integer); function Compare(Other: TSimbaImage): Single; @@ -264,22 +264,20 @@ implementation simba.image_lazbridge, simba.image_integral, simba.image_gaussblur, simba.image_bitmaparealoader, simba.image_stringconv; -function TSimbaImage.SaveToFile(FileName: String; OverwriteIfExists: Boolean): Boolean; +function TSimbaImage.Save(FileName: String; OverwriteIfExists: Boolean): Boolean; var Stream: TFileStream; WriterClass: TFPCustomImageWriterClass; - Writer: TFPCustomImageWriter; begin Result := False; if FileExists(FileName) and (not OverwriteIfExists) then - SimbaException('TSimbaImage.SaveToFile: File already exists "%s"', [FileName]); + SimbaException('TSimbaImage.Save: File already exists "%s"', [FileName]); WriterClass := TFPCustomImage.FindWriterFromFileName(FileName); if (WriterClass = nil) then - SimbaException('TSimbaImage.SaveToFile: Unknown image format "%s"', [FileName]); + SimbaException('TSimbaImage.Save: Unknown image format "%s"', [FileName]); - Writer := WriterClass.Create(); Stream := nil; try if FileExists(FileName) then @@ -287,21 +285,17 @@ function TSimbaImage.SaveToFile(FileName: String; OverwriteIfExists: Boolean): B else Stream := TFileStream.Create(FileName, fmCreate or fmShareDenyWrite); - SimbaImage_ToFPImageWriter(Self, Writer, Stream); + SimbaImage_ToFPImageWriter(Self, WriterClass, Stream); Result := True; finally - if (Stream <> nil) then - Stream.Free(); - if (Writer <> nil) then - Writer.Free(); + Stream.Free(); end; end; -procedure TSimbaImage.LoadFromFile(FileName: String); +procedure TSimbaImage.Load(FileName: String); var ReaderClass: TFPCustomImageReaderClass; - Reader: TFPCustomImageReader; Stream: TFileStream; begin if (not FileExists(FileName)) then @@ -310,18 +304,16 @@ procedure TSimbaImage.LoadFromFile(FileName: String); ReaderClass := TFPCustomImage.FindReaderFromFileName(FileName); if (ReaderClass = nil) then SimbaException('TSimbaImage.LoadFromFile: Unknown image format "%s"', [FileName]); - Reader := ReaderClass.Create(); Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite); try - SimbaImage_FromFPImageReader(Self, Reader, Stream); + SimbaImage_FromFPImageReader(Self, ReaderClass, Stream); finally - Reader.Free(); Stream.Free(); end; end; -procedure TSimbaImage.LoadFromFile(FileName: String; Area: TBox); +procedure TSimbaImage.Load(FileName: String; Area: TBox); begin if (not FileExists(FileName)) then SimbaException('TSimbaImage.LoadFromFile: File not found "%s"', [FileName]); @@ -330,7 +322,7 @@ procedure TSimbaImage.LoadFromFile(FileName: String; Area: TBox); SimbaImage_LoadBitmapArea(Self, FileName, Area) else begin - LoadFromFile(FileName); + Load(FileName); Area := Area.Clip(TBox.Create(0, 0, FWidth - 1, FHeight - 1)); if (Area.Width > 1) and (Area.Height > 1) then @@ -350,8 +342,8 @@ function TSimbaImage.Copy(X1, Y1, X2, Y2: Integer): TSimbaImage; var Y: Integer; begin - AssertInImage('Copy', X1, Y1); - AssertInImage('Copy', X2, Y2); + if (not InImage(X1, Y1)) then RaiseOutOfImageException(X1, Y1); + if (not InImage(X2, Y2)) then RaiseOutOfImageException(X2, Y2); Result := TSimbaImage.Create(); Result.SetSize(X2-X1+1, Y2-Y1+1); @@ -363,8 +355,8 @@ procedure TSimbaImage.Crop(X1, Y1, X2, Y2: Integer); var Y: Integer; begin - AssertInImage('Crop', X1, Y1); - AssertInImage('Crop', X2, Y2); + if (not InImage(X1, Y1)) then RaiseOutOfImageException(X1, Y1); + if (not InImage(X2, Y2)) then RaiseOutOfImageException(X2, Y2); for Y := Y1 to Y2 do Move(FData[Y * FWidth + X1], FData[(Y-Y1) * FWidth], FWidth * SizeOf(TColorBGRA)); @@ -408,8 +400,8 @@ function TSimbaImage.ToMatrix(X1, Y1, X2, Y2: Integer): TIntegerMatrix; var X, Y: Integer; begin - AssertInImage('ToMatrix', X1, Y1); - AssertInImage('ToMatrix', X2, Y2); + if (not InImage(X1, Y1)) then RaiseOutOfImageException(X1, Y1); + if (not InImage(X2, Y2)) then RaiseOutOfImageException(X2, Y2); Result.SetSize(X2-X1+1, Y2-Y1+1); @@ -422,7 +414,6 @@ function TSimbaImage.ToMatrix(X1, Y1, X2, Y2: Integer): TIntegerMatrix; procedure TSimbaImage.DrawMatrix(Matrix: TIntegerMatrix); var X, Y, W, H: Integer; - Color: Integer; begin SetSize(Matrix.Width, Matrix.Height); @@ -430,11 +421,11 @@ procedure TSimbaImage.DrawMatrix(Matrix: TIntegerMatrix); H := FHeight - 1; for Y := 0 to H do for X := 0 to W do - begin - Color := Matrix[Y, X]; - - FData[Y * FWidth + X] := TColorBGRA((Color shr B_BIT and $FF) or (Color shr G_BIT and $FF) shl G_BIT or (Color shr R_BIT and $FF) shl B_BIT); - end; + FData[Y * FWidth + X] := TColorBGRA( + (Matrix[Y, X] shr B_BIT and $FF) or + (Matrix[Y, X] shr G_BIT and $FF) shl G_BIT or + (Matrix[Y, X] shr R_BIT and $FF) shl B_BIT + ); end; procedure TSimbaImage.DrawMatrix(Matrix: TSingleMatrix; ColorMapID: Integer = 0); @@ -494,25 +485,23 @@ function TSimbaImage.SaveToString: String; Result := SimbaImage_ToString(Self); end; -procedure TSimbaImage.LoadFromString(Str: String); +procedure TSimbaImage.FromString(Str: String); begin SimbaImage_FromString(Self, Str); end; -procedure TSimbaImage.LoadFromStream(Stream: TStream; FileName: String); +procedure TSimbaImage.FromStream(Stream: TStream; FileName: String); var ReaderClass: TFPCustomImageReaderClass; - Reader: TFPCustomImageReader; begin ReaderClass := TFPCustomImage.FindReaderFromFileName(FileName); if (ReaderClass = nil) then SimbaException('TSimbaImage.LoadFromStream: Unknown image format "%s"', [FileName]); - Reader := ReaderClass.Create(); - SimbaImage_FromFPImageReader(Self, Reader, Stream); - Reader.Free(); + + SimbaImage_FromFPImageReader(Self, ReaderClass, Stream); end; -procedure TSimbaImage.LoadFromData(AWidth, AHeight: Integer; AData: PColorBGRA; ADataWidth: Integer); +procedure TSimbaImage.FromData(AWidth, AHeight: Integer; AData: PColorBGRA; ADataWidth: Integer); var Y: Integer; begin @@ -521,10 +510,9 @@ procedure TSimbaImage.LoadFromData(AWidth, AHeight: Integer; AData: PColorBGRA; Exit; if (ADataWidth <> AWidth) then - begin for Y := 0 to AHeight - 1 do Move(AData[Y * ADataWidth], FData[Y * FWidth], FWidth * SizeOf(TColorBGRA)) - end else + else Move(AData^, FData^, FWidth * FHeight * SizeOf(TColorBGRA)); end; @@ -678,7 +666,7 @@ function TSimbaImage.PixelDifferenceTPA(Other: TSimbaImage): TPointArray; for X := 0 to W do begin if (not P1^.EqualsIgnoreAlpha(P2^)) then - Buffer.Add(X, Y); + {%H-}Buffer.Add(X, Y); Inc(P1); Inc(P2); @@ -717,14 +705,14 @@ function TSimbaImage.PixelDifferenceTPA(Other: TSimbaImage; Tolerance: Single): Result := Buffer.ToArray(False); end; -procedure TSimbaImage.LoadFromLazBitmap(LazBitmap: TBitmap); +procedure TSimbaImage.FromLazBitmap(LazBitmap: TBitmap); var TempBitmap: TSimbaImage; begin SetSize(0, 0); TempBitmap := LazImage_ToSimbaImage(LazBitmap); - TempBitmap.DataOwner := False; + TempBitmap.FDataOwner := False; FData := TempBitmap.Data; FWidth := TempBitmap.Width; @@ -733,13 +721,6 @@ procedure TSimbaImage.LoadFromLazBitmap(LazBitmap: TBitmap); TempBitmap.Free(); end; -procedure TSimbaImage.LoadFromImage(Image: TSimbaImage); -begin - SetSize(Image.Width, Image.Height); - - Move(Image.FData^, FData^, FWidth * FHeight * SizeOf(TColorBGRA)); -end; - procedure TSimbaImage.DrawTPA(TPA: TPointArray; Color: TColor; Alpha: Byte); begin if (Alpha = 0) then @@ -1129,6 +1110,28 @@ procedure TSimbaImage.ClearInverted(Box: TBox); Self.Clear(TBox.Create(Box.X2 + 1, Box.Y2 + 1, FWidth-1, FHeight - 1)); //Btm Right end; +procedure TSimbaImage.SplitChannels(out B,G,R,A: TByteArray); +var + I: Integer; + Ptr: PColorBGRA; +begin + SetLength(B, FWidth*FHeight); + SetLength(G, FWidth*FHeight); + SetLength(R, FWidth*FHeight); + SetLength(A, FWidth*FHeight); + + Ptr := FData; + for I := 0 to FWidth * FHeight - 1 do + begin + B[I] := Ptr^.B; + G[I] := Ptr^.G; + R[I] := Ptr^.R; + A[I] := Ptr^.A; + + Inc(Ptr); + end; +end; + procedure TSimbaImage.DrawImage(Image: TSimbaImage; Location: TPoint; Alpha: Byte = 0); begin if (Alpha = 0) then @@ -1611,7 +1614,7 @@ function TSimbaImage.BoxBlur(Radius: Integer): TSimbaImage; for Y := 0 to H do for X := 0 to W do begin - if (FData[Y * FWidth + X].A > 0) then + if (FData[Y * FWidth + X].A > ALPHA_TRANSPARENT) then begin B.X1 := Max(X-Radius, 0); B.Y1 := Max(Y-Radius, 0); @@ -1643,6 +1646,40 @@ function TSimbaImage.BoxBlur(Radius: Integer): TSimbaImage; end; end; +function TSimbaImage.GaussBlur(Radius: Double): TSimbaImage; +var + B,G,R,A: TByteArray; + Ignore: TBooleanArray; + I: Integer; + Ptr: PColorBGRA; +begin + Result := TSimbaImage.Create(FWidth, FHeight); + if (FWidth * FHeight = 0) then + Exit; + + SplitChannels(B,G,R,A); + + SetLength(Ignore, Length(A)); + for I := 0 to High(Ignore) do + Ignore[I] := (A[I] = ALPHA_TRANSPARENT); + + imgGaussBlur(Radius, R,G,B, Ignore, FWidth, FHeight); + + Ptr := Result.Data; + for i := 0 to (FWidth * FHeight) - 1 do + begin + Ptr^.A := A[I]; + if (Ptr^.A > ALPHA_TRANSPARENT) then + begin + Ptr^.B := B[I]; + Ptr^.G := G[I]; + Ptr^.R := R[I]; + end; + + Inc(Ptr); + end; +end; + function TSimbaImage.Convolute(Matrix: TDoubleMatrix): TSimbaImage; var X, Y, YY, XX, CX, CY: Integer; @@ -1718,58 +1755,9 @@ function TSimbaImage.Mirror(Style: ESimbaImageMirrorStyle): TSimbaImage; for X := FHeight - 1 downto 0 do Result.FData[X*FHeight+Y] := FData[Y*FWidth+X]; end; - end; -end; - -function TSimbaImage.GaussBlur(Radius: Double): TSimbaImage; -var - r,g,b: TByteArray; - i: Integer; - ptr: PColorBGRA; - ptrR, ptrG, ptrB: PByte; -begin - Result := TSimbaImage.Create(FWidth, FHeight); - if (FWidth = 0) or (FHeight = 0) then - Exit; - - SetLength(r, FWidth*FHeight); - SetLength(g, FWidth*FHeight); - SetLength(b, FWidth*FHeight); - - ptr := FData; - ptrR := @r[0]; - ptrG := @g[0]; - ptrB := @b[0]; - - for i := 0 to (FWidth * FHeight) - 1 do - begin - ptrR^ := ptr^.R; - ptrG^ := ptr^.G; - ptrB^ := ptr^.B; - - Inc(ptr); - Inc(ptrR); - Inc(ptrG); - Inc(ptrB); - end; - - imgGaussBlur(Radius, r,g,b, FWidth, FHeight); - - ptr := Result.FData; - ptrR := @r[0]; - ptrG := @g[0]; - ptrB := @b[0]; - for i := 0 to (FWidth * FHeight) - 1 do - begin - ptr^.R := ptrR^; - ptr^.G := ptrG^; - ptr^.B := ptrB^; - - Inc(ptr); - Inc(ptrR); - Inc(ptrG); - Inc(ptrB); + else + Result := nil; end; end; @@ -1901,7 +1889,7 @@ function TSimbaImage.GetFontName: String; Result := FTextDrawer.FontName; end; -class function TSimbaImage.LoadedFontNames: TStringArray; +class function TSimbaImage.FontNames: TStringArray; begin Result := SimbaFreeTypeFontLoader.FontNames; end; @@ -1971,7 +1959,7 @@ procedure TSimbaImage.DrawText(Text: String; Position: TPoint; Color: TColor); FTextDrawer.DrawText(Text, Position, Color); end; -procedure TSimbaImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); +procedure TSimbaImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); begin FTextDrawer.DrawText(Text, Box, Alignments, Color); end; @@ -2187,7 +2175,9 @@ function TSimbaImage.GetPixels(Points: TPointArray): TColorArray; for I := 0 to High(Points) do with Points[I] do begin - AssertInImage('GetPixels', X, Y); + if (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then + RaiseOutOfImageException(X, Y); + with FData[Y * FWidth + X] do Result[I] := TColor(R or G shl G_BIT or B shl B_BIT); end; @@ -2203,7 +2193,8 @@ procedure TSimbaImage.SetPixels(Points: TPointArray; Colors: TColorArray); for I := 0 to High(Points) do with Points[I] do begin - AssertInImage('SetPixels', X, Y); + if (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then + RaiseOutOfImageException(X, Y); FData[Y * FWidth + X] := Colors[I].ToBGRA(); end; @@ -2766,13 +2757,18 @@ procedure TSimbaImage._DrawImageAlpha(Image: TSimbaImage; P: TPoint; Alpha: Byte end; end; +procedure TSimbaImage.RaiseOutOfImageException(X, Y: Integer); +begin + SimbaException('%d,%d is outside the image bounds (0,0,%d,%d)', [X, Y, FWidth-1, FHeight-1]); +end; + procedure TSimbaImage.NotifyUnfreed; begin inherited NotifyUnfreed(); if (SaveUnfreedImages <> '') then try - SaveToFile(IncludeTrailingPathDelimiter(SetDirSeparators(SaveUnfreedImages)) + IntToStr(PtrUInt(Self)) + '.bmp'); + Save(IncludeTrailingPathDelimiter(SetDirSeparators(SaveUnfreedImages)) + IntToStr(PtrUInt(Self)) + '.bmp'); except on E: Exception do DebugLn(E.ToString); @@ -2781,7 +2777,8 @@ procedure TSimbaImage.NotifyUnfreed; function TSimbaImage.GetPixel(const X, Y: Integer): TColor; begin - AssertInImage('GetPixel', X, Y); + if (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then + RaiseOutOfImageException(X, Y); with FData[Y * FWidth + X] do Result := R or G shl G_BIT or B shl B_BIT; @@ -2789,7 +2786,8 @@ function TSimbaImage.GetPixel(const X, Y: Integer): TColor; procedure TSimbaImage.SetPixel(X, Y: Integer; Color: TColor); begin - AssertInImage('SetPixel', X, Y); + if (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then + RaiseOutOfImageException(X, Y); FData[Y * FWidth + X] := Color.ToBGRA(); end; @@ -2799,12 +2797,6 @@ function TSimbaImage.InImage(const X, Y: Integer): Boolean; Result := (X >= 0) and (Y >= 0) and (X < FWidth) and (Y < FHeight); end; -procedure TSimbaImage.AssertInImage(const Method: String; const X, Y: Integer); -begin - if (X < 0) or (Y < 0) or (X >= FWidth) or (Y >= FHeight) then - SimbaException('TSimbaImage.%s: %d,%d is outside the image bounds: %d,%d,%d,%d', [Method, X, Y, 0,0,FWidth-1,FHeight-1]); -end; - procedure TSimbaImage.DrawLineAA(Start, Stop: TPoint; Color: TColor; Thickness: Single); var RGB: TColorBGRA; @@ -3087,7 +3079,7 @@ constructor TSimbaImage.CreateFromFile(FileName: String); begin Create(); - LoadFromFile(FileName); + Load(FileName); end; constructor TSimbaImage.CreateFromZip(ZipFileName, ZipEntryName: String); @@ -3098,7 +3090,7 @@ constructor TSimbaImage.CreateFromZip(ZipFileName, ZipEntryName: String); if ZipExtractOne(ZipFileName, ZipEntryName, Stream) then try - LoadFromStream(Stream, ZipEntryName); + FromStream(Stream, ZipEntryName); finally Stream.Free(); end; @@ -3108,14 +3100,14 @@ constructor TSimbaImage.CreateFromString(Str: String); begin Create(); - LoadFromString(Str); + FromString(Str); end; constructor TSimbaImage.CreateFromData(AWidth, AHeight: Integer; AData: PColorBGRA; ADataWidth: Integer); begin Create(); - LoadFromData(AWidth, AHeight, AData, ADataWidth); + FromData(AWidth, AHeight, AData, ADataWidth); end; constructor TSimbaImage.CreateFromWindow(Window: TWindowHandle); @@ -3128,7 +3120,7 @@ constructor TSimbaImage.CreateFromWindow(Window: TWindowHandle); if SimbaNativeInterface.GetWindowBounds(Window, B) and SimbaNativeInterface.GetWindowImage(Window, 0, 0, B.Width - 1, B.Height - 1, ImageData) then try - LoadFromData(B.Width - 1, B.Height - 1, ImageData, B.Width - 1); + FromData(B.Width - 1, B.Height - 1, ImageData, B.Width - 1); finally FreeMem(ImageData); end; @@ -3139,8 +3131,7 @@ destructor TSimbaImage.Destroy; if FDataOwner then SetSize(0, 0); - if (FTextDrawer <> nil) then - FreeAndNil(FTextDrawer); + FreeAndNil(FTextDrawer); inherited Destroy(); end; diff --git a/Source/image/simba.image_gaussblur.pas b/Source/image/simba.image_gaussblur.pas index d92077cd9..55aa524e8 100644 --- a/Source/image/simba.image_gaussblur.pas +++ b/Source/image/simba.image_gaussblur.pas @@ -1,4 +1,7 @@ // https://blog.ivank.net/fastest-gaussian-blur.html +// Olly: +// Hacked in `ignore` param to ignore a pixel, seems to work at first glance. +// This does mean the edges will be sharp, but might be useful. unit simba.image_gaussblur; {$i simba.inc} @@ -9,7 +12,7 @@ interface Classes, SysUtils, simba.base; -procedure imgGaussBlur(radius: Double; var r,g,b: TByteArray; width, height: Integer); +procedure imgGaussBlur(radius: Double; var r,g,b: TByteArray; ignore: TBooleanArray; width, height: Integer); implementation @@ -42,7 +45,7 @@ function boxesForGauss(sigma: Double; n: Integer): TIntegerArray; end; end; -procedure boxBlurH_4(var scl, tcl: TByteArray; w, h: Integer; r: Integer); +procedure boxBlurH_4(var scl, tcl: TByteArray; ignore: TBooleanArray; w, h: Integer; r: Integer); var iarr: Double; i,j: Integer; @@ -54,6 +57,9 @@ procedure boxBlurH_4(var scl, tcl: TByteArray; w, h: Integer; r: Integer); for i := 0 to h-1 do begin ti := i * w; + if (ignore[ti]) then + Continue; + li := ti; ri := Round(ti + r); fv := scl[ti]; @@ -90,7 +96,7 @@ procedure boxBlurH_4(var scl, tcl: TByteArray; w, h: Integer; r: Integer); end; end; -procedure boxBlurT_4(var scl, tcl: TByteArray; w, h: Integer; r: Integer); +procedure boxBlurT_4(var scl, tcl: TByteArray; ignore: TBooleanArray; w, h: Integer; r: Integer); var iarr: Double; i,j: Integer; @@ -138,25 +144,22 @@ procedure boxBlurT_4(var scl, tcl: TByteArray; w, h: Integer; r: Integer); end; end; -procedure boxBlur_4(var scl, tcl: TByteArray; w,h: Integer; r: Integer); -var - i: Integer; +procedure boxBlur_4(var scl, tcl: TByteArray; skip: TBooleanArray; w,h: Integer; r: Integer); begin - for i:=0 to High(scl) do - tcl[i] := scl[i]; + Move(scl[0], tcl[0], Length(scl) * SizeOf(Byte)); - boxBlurH_4(tcl, scl, w, h, r); - boxBlurT_4(scl, tcl, w, h, r); + boxBlurH_4(tcl, scl, skip, w, h, r); + boxBlurT_4(scl, tcl, skip, w, h, r); end; -procedure gaussBlur_4(var scl, tcl: TByteArray; w,h: Integer; r: Double; bxs: TIntegerArray); +procedure gaussBlur_4(var scl, tcl: TByteArray; skip: TBooleanArray; w,h: Integer; r: Double; bxs: TIntegerArray); begin - boxBlur_4(scl, tcl, w, h, (bxs[0] - 1) div 2); - boxBlur_4(tcl, scl, w, h, (bxs[1] - 1) div 2); - boxBlur_4(scl, tcl, w, h, (bxs[2] - 1) div 2); + boxBlur_4(scl, tcl, skip, w, h, (bxs[0] - 1) div 2); + boxBlur_4(tcl, scl, skip, w, h, (bxs[1] - 1) div 2); + boxBlur_4(scl, tcl, skip, w, h, (bxs[2] - 1) div 2); end; -procedure imgGaussBlur(radius: Double; var r, g, b: TByteArray; width, height: Integer); +procedure imgGaussBlur(radius: Double; var r, g, b: TByteArray; ignore: TBooleanArray; width, height: Integer); var outR, outG, outB: TByteArray; boxes: TIntegerArray; @@ -167,9 +170,9 @@ procedure imgGaussBlur(radius: Double; var r, g, b: TByteArray; width, height: I boxes := boxesForGauss(radius, 3); - gaussBlur_4(r, outR, width, height, radius, boxes); - gaussBlur_4(g, outG, width, height, radius, boxes); - gaussBlur_4(b, outB, width, height, radius, boxes); + gaussBlur_4(r, outR, ignore, width, height, radius, boxes); + gaussBlur_4(g, outG, ignore, width, height, radius, boxes); + gaussBlur_4(b, outB, ignore, width, height, radius, boxes); r := outR; g := outG; diff --git a/Source/image/simba.image_lazbridge.pas b/Source/image/simba.image_lazbridge.pas index c2806be96..b4d7f891e 100644 --- a/Source/image/simba.image_lazbridge.pas +++ b/Source/image/simba.image_lazbridge.pas @@ -18,7 +18,7 @@ interface {$scopedenums on} type - ELazPixelFormat = (BGR, BGRA, RGB, RGBA, ARGB); + ELazPixelFormat = (UNKNOWN, BGR, BGRA, RGB, RGBA, ARGB); {$scopedenums off} procedure LazImage_CopyRow_BGR(Source: PColorBGRA; SourceUpper: PtrUInt; Dest: PColorBGR); inline; @@ -30,8 +30,8 @@ procedure LazImage_FromSimbaImage(LazImage: TBitmap; SimbaImage: TSimbaImage); function LazImage_ToSimbaImage(LazImage: TBitmap): TSimbaImage; function LazImage_PixelFormat(LazImage: TBitmap): ELazPixelFormat; -procedure SimbaImage_ToFPImageWriter(SimbaImage: TSimbaImage; Writer: TFPCustomImageWriter; Stream: TStream); -procedure SimbaImage_FromFPImageReader(SimbaImage: TSimbaImage; Reader: TFPCustomImageReader; Stream: TStream); +procedure SimbaImage_ToFPImageWriter(SimbaImage: TSimbaImage; WriterClass: TFPCustomImageWriterClass; Stream: TStream); +procedure SimbaImage_FromFPImageReader(SimbaImage: TSimbaImage; ReaderClass: TFPCustomImageReaderClass; Stream: TStream); function SimbaImage_ToRawImage(SimbaImage: TSimbaImage): TRawImage; function SimbaImage_ToLazImage(SimbaImage: TSimbaImage): TBitmap; @@ -264,6 +264,8 @@ function LazImage_PixelFormat(LazImage: TBitmap): ELazPixelFormat; var ChannelCount: Integer; begin + Result := ELazPixelFormat.UNKNOWN; + with LazImage.RawImage.Description do begin if ((BitsPerPixel and 7) <> 0) then @@ -298,15 +300,17 @@ function LazImage_PixelFormat(LazImage: TBitmap): ELazPixelFormat; end; end; -procedure SimbaImage_ToFPImageWriter(SimbaImage: TSimbaImage; Writer: TFPCustomImageWriter; Stream: TStream); +procedure SimbaImage_ToFPImageWriter(SimbaImage: TSimbaImage; WriterClass: TFPCustomImageWriterClass; Stream: TStream); var Img: TLazIntfImage; + Writer: TFPCustomImageWriter; begin Img := nil; + Writer := nil; try + Writer := WriterClass.Create(); Img := TLazIntfImage.Create(SimbaImage_ToRawImage(SimbaImage), False); - Writer.ImageWrite(Stream, Img); finally if Assigned(Img) then @@ -314,21 +318,25 @@ procedure SimbaImage_ToFPImageWriter(SimbaImage: TSimbaImage; Writer: TFPCustomI end; end; -procedure SimbaImage_FromFPImageReader(SimbaImage: TSimbaImage; Reader: TFPCustomImageReader; Stream: TStream); +procedure SimbaImage_FromFPImageReader(SimbaImage: TSimbaImage; ReaderClass: TFPCustomImageReaderClass; Stream: TStream); var Img: TLazIntfImage; + Reader: TFPCustomImageReader; begin Img := nil; + Reader := nil; try + Reader := ReaderClass.Create(); + Img := TLazIntfImage.Create(0, 0); Img.DataDescription := SimbaRawImgDescription; Reader.ImageRead(Stream, Img); - SimbaImage.LoadFromData(Img.Width, Img.Height, PColorBGRA(Img.PixelData), Img.Width); + SimbaImage.FromData(Img.Width, Img.Height, PColorBGRA(Img.PixelData), Img.Width); finally - if Assigned(Img) then - Img.Free(); + Img.Free(); + Reader.Free(); end; end; diff --git a/Source/image/simba.image_textdrawer.pas b/Source/image/simba.image_textdrawer.pas index c6dc849b0..ffc3f4959 100644 --- a/Source/image/simba.image_textdrawer.pas +++ b/Source/image/simba.image_textdrawer.pas @@ -15,8 +15,6 @@ interface type TSimbaFreeTypeFontLoader = class - private - function GetFontNames: TStringArray; protected type TFontCacheEntry = record @@ -31,6 +29,8 @@ TFontCacheEntry = record FSystemFontsLoaded: Boolean; procedure LoadSystemFonts; + + function GetFontNames: TStringArray; public function LoadFonts(Dir: String): Boolean; function GetFont(AName: String; ASize: Single; AAntialised, ABold, AItalic: Boolean): TFreeTypeFont; @@ -39,8 +39,8 @@ TFontCacheEntry = record end; {$scopedenums on} - ETextDrawAlignment = (LEFT, CENTER, RIGHT, JUSTIFY, TOP, VERTICAL_CENTER, BASE_LINE, BOTTOM); - ETextDrawAlignmentSet = set of ETextDrawAlignment; + ETextDrawAlign = (LEFT, CENTER, RIGHT, JUSTIFY, TOP, VERTICAL_CENTER, BASE_LINE, BOTTOM); + ETextDrawAlignSet = set of ETextDrawAlign; {$scopedenums off} TSimbaTextDrawer = class(TFPImageFreeTypeDrawer) @@ -81,7 +81,7 @@ TSimbaTextDrawer = class(TFPImageFreeTypeDrawer) property DrawnBox: TBox read FDrawnBox; procedure DrawText(Text: String; Position: TPoint; Color: TColor); overload; - procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); overload; + procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); overload; function TextWidth(Text: String): Integer; function TextHeight(Text: String): Integer; @@ -97,7 +97,7 @@ implementation uses Forms, FileUtil, LazFileUtils, LazFreeTypeFontCollection, - simba.image, simba.image_utils; + simba.image, simba.image_utils, simba.fonthelpers; function TSimbaFreeTypeFontLoader.GetFontNames: TStringArray; begin @@ -363,6 +363,7 @@ constructor TSimbaTextDrawer.Create(SimbaImage: TObject); FSimbaImage := SimbaImage; FSize := 20; FFontAntialised := False; + FFontName := GetDefaultFontName(); end; procedure TSimbaTextDrawer.DrawText(Text: String; Position: TPoint; Color: TColor); @@ -375,7 +376,7 @@ procedure TSimbaTextDrawer.DrawText(Text: String; Position: TPoint; Color: TColo end; end; -procedure TSimbaTextDrawer.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); +procedure TSimbaTextDrawer.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); var FreeTypeAlignments: TFreeTypeAlignments absolute Alignments; begin diff --git a/Source/script/imports/simba.import_externalimage.pas b/Source/script/imports/simba.import_externalimage.pas index 0dbb05534..367f40e48 100644 --- a/Source/script/imports/simba.import_externalimage.pas +++ b/Source/script/imports/simba.import_externalimage.pas @@ -198,7 +198,7 @@ procedure _LapeExternalImage_DrawText(const Params: PParamArray); LAPE_WRAPPER_C *) procedure _LapeExternalImage_DrawTextEx(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaExternalImage(Params^[0])^.DrawText(PString(Params^[1])^, PBox(Params^[2])^, ETextDrawAlignmentSet(Params^[3]^), PColor(Params^[4])^); + PSimbaExternalImage(Params^[0])^.DrawText(PString(Params^[1])^, PBox(Params^[2])^, ETextDrawAlignSet(Params^[3]^), PColor(Params^[4])^); end; (* @@ -420,7 +420,7 @@ procedure ImportSimbaExternalImage(Compiler: TSimbaScript_Compiler); addGlobalFunc('function TExternalImage.TextSize(Text: String): TPoint;', @_LapeExternalImage_TextSize); addGlobalFunc('procedure TExternalImage.DrawText(Text: String; Position: TPoint; Color: TColor); overload', @_LapeExternalImage_DrawText); - addGlobalFunc('procedure TExternalImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); overload', @_LapeExternalImage_DrawTextEx); + addGlobalFunc('procedure TExternalImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); overload', @_LapeExternalImage_DrawTextEx); addGlobalFunc('procedure TExternalImage.DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor);', @_LapeExternalImage_DrawTextLines); addGlobalFunc('procedure TExternalImage.Fill(Color: TColor; Alpha: Byte)', @_LapeExternalImage_Fill); diff --git a/Source/script/imports/simba.import_image.pas b/Source/script/imports/simba.import_image.pas index 8e585a777..92a071a90 100644 --- a/Source/script/imports/simba.import_image.pas +++ b/Source/script/imports/simba.import_image.pas @@ -124,7 +124,7 @@ procedure _LapeImage_Height_Read(const Params: PParamArray; const Result: Pointe ~~~~~~~~~~~~~~~~~~~~~~ > procedure TImage.SetExternalData(AData: PColorBGRA; AWidth, AHeight: Integer); *) -procedure _LapeImage_SetPersistentMemory(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_SetExternalData(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin PSimbaImage(Params^[0])^.SetExternalData(PPointer(Params^[1])^, PInteger(Params^[2])^, PInteger(Params^[3])^); end; @@ -134,7 +134,7 @@ procedure _LapeImage_SetPersistentMemory(const Params: PParamArray); LAPE_WRAPPE ~~~~~~~~~~~~~~~~~~~~~~~~ > procedure TImage.ResetExternalData; *) -procedure _LapeImage_ResetPersistentMemory(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_ResetExternalData(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin PSimbaImage(Params^[0])^.ResetExternalData(); end; @@ -144,9 +144,9 @@ procedure _LapeImage_ResetPersistentMemory(const Params: PParamArray); LAPE_WRAP ~~~~~~~~~~~~~~~~~ > function TImage.SaveToFile(FileName: String; OverwriteIfExists: Boolean = False): Boolean; *) -procedure _LapeImage_SaveToFile(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_Save(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin - PBoolean(Result)^ := PSimbaImage(Params^[0])^.SaveToFile(PString(Params^[1])^, PBoolean(Params^[2])^); + PBoolean(Result)^ := PSimbaImage(Params^[0])^.Save(PString(Params^[1])^, PBoolean(Params^[2])^); end; (* @@ -164,9 +164,9 @@ procedure _LapeImage_SaveToString(const Params: PParamArray; const Result: Point ~~~~~~~~~~~~~~~~~~~ > procedure TImage.LoadFromFile(FileName: String); *) -procedure _LapeImage_LoadFromFile(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_Load1(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.LoadFromFile(PString(Params^[1])^); + PSimbaImage(Params^[0])^.Load(PString(Params^[1])^); end; (* @@ -174,9 +174,9 @@ procedure _LapeImage_LoadFromFile(const Params: PParamArray); LAPE_WRAPPER_CALLI ~~~~~~~~~~~~~~~~~~~ > procedure TImage.LoadFromFile(FileName: String; Area: TBox); *) -procedure _LapeImage_LoadFromFileEx(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_Load2(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.LoadFromFile(PString(Params^[1])^, PBox(Params^[2])^); + PSimbaImage(Params^[0])^.Load(PString(Params^[1])^, PBox(Params^[2])^); end; (* @@ -328,9 +328,9 @@ procedure _LapeImage_ToLazBitmap(const Params: PParamArray; const Result: Pointe ~~~~~~~~~~~~~~~~~~~~~~~~ > procedure TImage.LoadFromLazBitmap(LazBitmap: TLazBitmap); *) -procedure _LapeImage_LoadFromLazBitmap(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_FromLazBitmap(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.LoadFromLazBitmap(PBitmap(Params^[1])^); + PSimbaImage(Params^[0])^.FromLazBitmap(PBitmap(Params^[1])^); end; (* @@ -935,7 +935,7 @@ procedure _LapeImage_DrawText(const Params: PParamArray); LAPE_WRAPPER_CALLING_C *) procedure _LapeImage_DrawTextEx(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.DrawText(PString(Params^[1])^, PBox(Params^[2])^, ETextDrawAlignmentSet(Params^[3]^), PColor(Params^[4])^); + PSimbaImage(Params^[0])^.DrawText(PString(Params^[1])^, PBox(Params^[2])^, ETextDrawAlignSet(Params^[3]^), PColor(Params^[4])^); end; (* @@ -1045,9 +1045,9 @@ procedure _LapeImage_PixelDifferenceToleranceTPA(const Params: PParamArray; cons ~~~~~~~~~~~~~~~~~~~~~ > procedure TImage.LoadFromString(Str: String); *) -procedure _LapeImage_LoadFromString(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_FromString(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.LoadFromString(PString(Params^[1])^); + PSimbaImage(Params^[0])^.FromString(PString(Params^[1])^); end; (* @@ -1055,19 +1055,9 @@ procedure _LapeImage_LoadFromString(const Params: PParamArray); LAPE_WRAPPER_CAL ~~~~~~~~~~~~~~~~~~~ > procedure TImage.LoadFromData(AWidth, AHeight: Integer; Memory: PColorBGRA; DataWidth: Integer); *) -procedure _LapeImage_LoadFromData(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_FromData(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV begin - PSimbaImage(Params^[0])^.LoadFromData(PInteger(Params^[1])^, PInteger(Params^[2])^, PPointer(Params^[3])^, PInteger(Params^[4])^); -end; - -(* -TImage.LoadFromImage -~~~~~~~~~~~~~~~~~~~~ -> procedure TImage.LoadFromImage(Image: TImage); -*) -procedure _LapeImage_LoadFromImage(const Params: PParamArray); LAPE_WRAPPER_CALLING_CONV -begin - PSimbaImage(Params^[0])^.LoadFromImage(PSimbaImage(Params^[1])^); + PSimbaImage(Params^[0])^.FromData(PInteger(Params^[1])^, PInteger(Params^[2])^, PPointer(Params^[3])^, PInteger(Params^[4])^); end; (* @@ -1163,15 +1153,15 @@ procedure _LapeImage_LoadFonts(const Params: PParamArray; const Result: Pointer) end; (* -TImage.GetFontNames -~~~~~~~~~~~~~~~~~~~ -> function TImage.GetFontNames: TStringArray; static; +TImage.FontNames +~~~~~~~~~~~~~~~~ +> function TImage.FontNames: TStringArray; static; Returns all the available font names. *) -procedure _LapeImage_LoadedFontNames(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV +procedure _LapeImage_FontNames(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV begin - PStringArray(Result)^ := TSimbaImage.LoadedFontNames(); + PStringArray(Result)^ := TSimbaImage.FontNames(); end; (* @@ -1282,28 +1272,26 @@ procedure ImportSimbaImage(Compiler: TSimbaScript_Compiler); addClass('TImage'); addGlobalType('array of TImage', 'TImageArray'); - addGlobalType('array of PColorBGRA', 'TImageRowPtrs'); addGlobalType('enum(WIDTH, HEIGHT, LINE)', 'EImageMirrorStyle'); addGlobalType('enum(MEAN, MIN_MAX)', 'EImageThreshMethod'); - addGlobalType('enum(LEFT, CENTER, RIGHT, JUSTIFY, TOP, VERTICAL_CENTER, BASE_LINE, BOTTOM)', 'ETextDrawAlignment'); - addGlobalType('set of ETextDrawAlignment', 'ETextDrawAlignmentSet'); + addGlobalType('enum(LEFT, CENTER, RIGHT, JUSTIFY, TOP, VERTICAL_CENTER, BASE_LINE, BOTTOM)', 'ETextDrawAlign'); + addGlobalType('set of ETextDrawAlign', 'ETextDrawAlignSet'); - addClassVar('TImage', 'Data', 'PColorBGRA', @_LapeImage_Data_Read); addClassVar('TImage', 'Name', 'String', @_LapeImage_Name_Read, @_LapeImage_Name_Write); - addClassVar('TImage', 'Width', 'Integer', @_LapeImage_Width_Read); - addClassVar('TImage', 'Height', 'Integer', @_LapeImage_Height_Read); - addClassVar('TImage', 'Center', 'TPoint', @_LapeImage_Center_Read); - addClassVar('TImage', 'FontName', 'String', @_LapeImage_FontName_Read, @_LapeImage_FontName_Write); addClassVar('TImage', 'FontSize', 'Single', @_LapeImage_FontSize_Read, @_LapeImage_FontSize_Write); addClassVar('TImage', 'FontAntialiasing', 'Boolean', @_LapeImage_FontAntialiasing_Read, @_LapeImage_FontAntialiasing_Write); addClassVar('TImage', 'FontBold', 'Boolean', @_LapeImage_FontBold_Read, @_LapeImage_FontBold_Write); addClassVar('TImage', 'FontItalic', 'Boolean', @_LapeImage_FontItalic_Read, @_LapeImage_FontItalic_Write); - addGlobalFunc('function TImage.LoadedFontNames: TStringArray; static;', @_LapeImage_LoadedFontNames); + addGlobalFunc('function TImage.FontNames: TStringArray; static;', @_LapeImage_FontNames); addGlobalFunc('function TImage.LoadFonts(Dir: String): Boolean; static;', @_LapeImage_LoadFonts); + addGlobalFunc('function TImage.Width: Integer', @_LapeImage_Width_Read); + addGlobalFunc('function TImage.Height: Integer', @_LapeImage_Height_Read); + addGlobalFunc('function TImage.Data: PColorBGRA', @_LapeImage_Data_Read); + addGlobalFunc('function TImage.Center: TPoint', @_LapeImage_Center_Read); addGlobalFunc('function TImage.InImage(X, Y: Integer): Boolean', @_LapeImage_InImage); addGlobalFunc('function TImage.Create: TImage; static; overload', @_LapeImage_Create); @@ -1334,7 +1322,7 @@ procedure ImportSimbaImage(Compiler: TSimbaScript_Compiler); addGlobalFunc('function TImage.TextHeight(Text: String): Integer;', @_LapeImage_TextHeight); addGlobalFunc('function TImage.TextSize(Text: String): TPoint;', @_LapeImage_TextSize); addGlobalFunc('procedure TImage.DrawText(Text: String; Position: TPoint; Color: TColor); overload', @_LapeImage_DrawText); - addGlobalFunc('procedure TImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); overload', @_LapeImage_DrawTextEx); + addGlobalFunc('procedure TImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); overload', @_LapeImage_DrawTextEx); addGlobalFunc('procedure TImage.DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor);', @_LapeImage_DrawTextLines); addGlobalFunc('procedure TImage.DrawATPA(ATPA: T2DPointArray; Color: TColor = -1; Alpha: Byte = 0);', @_LapeImage_DrawATPA); @@ -1380,8 +1368,8 @@ procedure ImportSimbaImage(Compiler: TSimbaScript_Compiler); addGlobalFunc('procedure TImage.DrawMatrix(Matrix: TSingleMatrix; ColorMapID: Integer = 0); overload', @_LapeImage_DrawMatrixF); addGlobalFunc('procedure TImage.SetSize(AWidth, AHeight: Integer);', @_LapeImage_SetSize); - addGlobalFunc('procedure TImage.SetPersistentMemory(Memory: PtrUInt; AWidth, AHeight: Integer);', @_LapeImage_SetPersistentMemory); - addGlobalFunc('procedure TImage.ResetPersistentMemory;', @_LapeImage_ResetPersistentMemory); + addGlobalFunc('procedure TImage.SetExternalData(Memory: PtrUInt; AWidth, AHeight: Integer);', @_LapeImage_SetExternalData); + addGlobalFunc('procedure TImage.ResetExternalData;', @_LapeImage_ResetExternalData); addGlobalFunc('function TImage.ResizeNN(AWidth, AHeight: Integer): TImage', @_LapeImage_ResizeNN); addGlobalFunc('function TImage.ResizeBilinear(AWidth, AHeight: Integer): TImage', @_LapeImage_ResizeBilinear); @@ -1414,17 +1402,16 @@ procedure ImportSimbaImage(Compiler: TSimbaScript_Compiler); addGlobalFunc('function TImage.ThresholdSauvola(Radius: Integer; Invert: Boolean = False; R: Single = 128; K: Single = 0.5): TImage', @_LapeImage_ThresholdSauvola); addGlobalFunc('procedure TImage.Pad(Amount: Integer)', @_LapeImage_Pad); - addGlobalFunc('procedure TImage.LoadFromFile(FileName: String); overload', @_LapeImage_LoadFromFile); - addGlobalFunc('procedure TImage.LoadFromFile(FileName: String; Area: TBox); overload', @_LapeImage_LoadFromFileEx); - addGlobalFunc('procedure TImage.LoadFromString(Str: String)', @_LapeImage_LoadFromString); - addGlobalFunc('procedure TImage.LoadFromData(AWidth, AHeight: Integer; AData: PColorBGRA; DataWidth: Integer)', @_LapeImage_LoadFromData); - addGlobalFunc('procedure TImage.LoadFromImage(Image: TImage);', @_LapeImage_LoadFromImage); - - addGlobalFunc('function TImage.SaveToFile(FileName: String; OverwriteIfExists: Boolean = False): Boolean;', @_LapeImage_SaveToFile); + addGlobalFunc('procedure TImage.Load(FileName: String); overload', @_LapeImage_Load1); + addGlobalFunc('procedure TImage.Load(FileName: String; Area: TBox); overload', @_LapeImage_Load2); + addGlobalFunc('function TImage.Save(FileName: String; OverwriteIfExists: Boolean = False): Boolean;', @_LapeImage_Save); addGlobalFunc('function TImage.SaveToString: String;', @_LapeImage_SaveToString); + addGlobalFunc('procedure TImage.FromString(Str: String)', @_LapeImage_FromString); + addGlobalFunc('procedure TImage.FromData(AWidth, AHeight: Integer; AData: PColorBGRA; DataWidth: Integer)', @_LapeImage_FromData); + addGlobalFunc('function TImage.ToLazBitmap: TLazBitmap;', @_LapeImage_ToLazBitmap); - addGlobalFunc('procedure TImage.LoadFromLazBitmap(LazBitmap: TLazBitmap);', @_LapeImage_LoadFromLazBitmap); + addGlobalFunc('procedure TImage.FromLazBitmap(LazBitmap: TLazBitmap);', @_LapeImage_FromLazBitmap); addGlobalFunc('function TImage.Compare(Other: TImage): Single;', @_LapeImage_Compare); addGlobalFunc('procedure TImage.SaveUnfreedImages(Directory: String); static;', @_LapeImage_SaveUnfreedImages); diff --git a/Source/simba.colorpicker.pas b/Source/simba.colorpicker.pas index bea619e14..8921cf68c 100644 --- a/Source/simba.colorpicker.pas +++ b/Source/simba.colorpicker.pas @@ -225,14 +225,14 @@ constructor TSimbaColorPicker.Create(Window: TWindowHandle); OnMouseUp := @ImageMouseUp; OnMouseMove := @ImageMouseMove; - with TSimbaImage.CreateFromWindow(DesktopWindow) do - try - Picture.Bitmap.LoadFromRawImage(SimbaImage_ToRawImage(GetSelf() as TSimbaImage), True); - - DataOwner := False; - finally - Free(); - end; + //with TSimbaImage.CreateFromWindow(DesktopWindow) do + //try + // Picture.Bitmap.LoadFromRawImage(SimbaImage_ToRawImage(GetSelf() as TSimbaImage), True); + // + // DataOwner := False; + //finally + // Free(); + //end; end; FHint := TSimbaColorPickerHint.Create(FForm); diff --git a/Source/simba.externalimage.pas b/Source/simba.externalimage.pas index 89f72d845..3d469b0c1 100644 --- a/Source/simba.externalimage.pas +++ b/Source/simba.externalimage.pas @@ -98,7 +98,7 @@ TSimbaExternalImage = class(TSimbaBaseClass) function TextSize(Text: String): TPoint; procedure DrawText(Text: String; Position: TPoint; Color: TColor); overload; - procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); overload; + procedure DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); overload; procedure DrawTextLines(Text: TStringArray; Position: TPoint; Color: TColor); // Image @@ -436,7 +436,7 @@ procedure TSimbaExternalImage.DrawText(Text: String; Position: TPoint; Color: TC addDirty(FBackBuffer.TextDrawer.DrawnBox); end; -procedure TSimbaExternalImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignmentSet; Color: TColor); +procedure TSimbaExternalImage.DrawText(Text: String; Box: TBox; Alignments: ETextDrawAlignSet; Color: TColor); begin CheckInUpdate(); diff --git a/Source/simba.fonthelpers.pas b/Source/simba.fonthelpers.pas index 24f107df7..fdf692844 100644 --- a/Source/simba.fonthelpers.pas +++ b/Source/simba.fonthelpers.pas @@ -17,6 +17,8 @@ function GetFontSize(Control: TWinControl; IncAmount: Integer = 0): Integer; function IsFontFixed(FontName: String): Boolean; function GetFixedFonts: TStringArray; +function GetDefaultFontName: String; + implementation uses @@ -111,5 +113,15 @@ function GetFixedFonts: TStringArray; end; end; +function GetDefaultFontName: String; +begin + with TBitmap.Create() do + try + Result := GetFontData(Canvas.Font.Reference.Handle).Name; + finally + Free(); + end; +end; + end. diff --git a/Tests/finder_color.simba b/Tests/finder_color.simba index f611247c2..9260c15c3 100644 --- a/Tests/finder_color.simba +++ b/Tests/finder_color.simba @@ -28,7 +28,7 @@ var I: Integer; begin Bitmap := TImage.Create(500, 500); - Bitmap.DrawHSLCircle(Bitmap.GetCenter(), 200); + Bitmap.DrawHSLCircle(Bitmap.Center(), 200); Target.SetImage(Bitmap); diff --git a/Tests/matchtemplatemask.simba b/Tests/matchtemplatemask.simba index 19506a7ed..be92012eb 100644 --- a/Tests/matchtemplatemask.simba +++ b/Tests/matchtemplatemask.simba @@ -51,7 +51,7 @@ begin img := TImage.CreateFromString('IMG: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'); templ := img.Copy(50, 50, 100, 100); - templ.DrawCircleInverted(templ.GetCenter(), 20, 0); + templ.DrawCircleInverted(templ.Center(), 20, 0); try test(TM_CCOEFF, [83, 1], [50, 50]); diff --git a/Third-Party/syncompletion_simba.pas b/Third-Party/syncompletion_simba.pas index 2aea25d66..67cbe1395 100644 --- a/Third-Party/syncompletion_simba.pas +++ b/Third-Party/syncompletion_simba.pas @@ -1475,8 +1475,11 @@ procedure TSynBaseCompletion.Execute(s: string; x, y: integer); CurrentString := s; - if p >= 0 then - Position := p; + //if p >= 0 then + // Position := p; + + TheForm.Position := 0; + TheForm.Scroll.Position := 0; if Assigned(OnExecute) then OnExecute(Self);