Skip to content

Commit

Permalink
Add Finder.HasColor
Browse files Browse the repository at this point in the history
  • Loading branch information
ollydev committed Feb 27, 2024
1 parent c8397e7 commit 9cf7444
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 35 deletions.
113 changes: 91 additions & 22 deletions Source/finders/simba.finder_color.pas
Original file line number Diff line number Diff line change
Expand Up @@ -12,29 +12,35 @@
{$DEFINE SIMBA_MAX_OPTIMIZATION}
{$i simba.inc}

{.$DEFINE SIMBA_BUFFERCHECKS}
{.$DEFINE SIMBA_BENCHMARKS}

interface

uses
Classes, SysUtils, Math, Graphics,
simba.base, simba.colormath, simba.colormath_distance, simba.target;
simba.base, simba.colormath, simba.colormath_distance, simba.target, simba.simplelock;

function FindColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers): TPointArray;

function FindColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer; OffsetX, OffsetY: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): TPointArray;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer; OffsetX, OffsetY: Integer): TPointArray;

function CountColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers): Integer;

function CountColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): Integer;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer): Integer;

procedure HasColorOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer; var Limit: TSimpleThreadsafeLimit);

function HasColorOnTarget(Target: TSimbaTarget; Bounds: TBox;
Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
MinCount: Integer): Boolean;

function MatchColorsOnBuffer(Formula: EColorSpace; Color: TColor; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): TSingleMatrix;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer): TSingleMatrix;

function MatchColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
Formula: EColorSpace; Color: TColor; Multipliers: TChannelMultipliers): TSingleMatrix;
Expand All @@ -49,7 +55,7 @@ implementation

uses
simba.arraybuffer, simba.colormath_distance_unrolled, simba.threadpool,
simba.array_pointarray, simba.matrix_float;
simba.array_pointarray, simba.matrix_float, simba.datetime;

// How much to "Slice" (vertically) the image up for multithreading.
function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;
Expand Down Expand Up @@ -158,14 +164,6 @@ function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;
Ptr := RowPtr;
for X := 0 to SearchWidth do
begin
{$IFDEF SIMBA_BUFFERCHECKS}
if (Ptr < BufferLo) or (Ptr > BufferHi) then
begin
DebugLn('Outside of buffer: %d, (Lo: %d, Hi: %d)', [PtrUInt(Ptr), PtrUInt(BufferLo), PtrUInt(BufferHi)]);
Halt;
end;
{$ENDIF}

if not Cache.Color.EqualsIgnoreAlpha(Ptr^) then
begin
Cache.Color := Ptr^;
Expand All @@ -176,6 +174,9 @@ function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;

Inc(Ptr);
end;

MACRO_FINDCOLORS_ROW

Inc(RowPtr, BufferWidth);
end;

Expand All @@ -184,7 +185,7 @@ function CalculateSlices(SearchWidth, SearchHeight: Integer): Integer;
}

function FindColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer; OffsetX, OffsetY: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): TPointArray;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer; OffsetX, OffsetY: Integer): TPointArray;
var
PointBuffer: TSimbaPointBuffer;

Expand All @@ -196,13 +197,16 @@ function FindColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Sing
if (Cache.Dist <= Tolerance) then
PointBuffer.Add(X + OffsetX, Y + OffsetY);
}
{$DEFINE MACRO_FINDCOLORS_ROW :=
// Nothing
}
{$DEFINE MACRO_FINDCOLORS_END :=
Result := PointBuffer.ToArray(False);
}
MACRO_FINDCOLORS

function CountColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): Integer;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer): Integer;

{$DEFINE MACRO_FINDCOLORS_BEGIN :=
Result := 0;
Expand All @@ -211,7 +215,12 @@ function CountColorsOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Sin
if (Cache.Dist <= Tolerance) then
Inc(Result);
}
{$DEFINE MACRO_FINDCOLORS_END := }
{$DEFINE MACRO_FINDCOLORS_ROW :=
// Nothing
}
{$DEFINE MACRO_FINDCOLORS_END :=
// Nothing
}
MACRO_FINDCOLORS

function FindColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
Expand All @@ -227,7 +236,6 @@ function FindColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
SliceResults[Index] := FindColorsOnBuffer(
Formula, Color, Tolerance, Multipliers,
@Buffer[Lo * BufferWidth], BufferWidth, Bounds.Width, (Hi - Lo) + 1, Bounds.X1, Bounds.Y1 + Lo
{$IFDEF SIMBA_BUFFERCHECKS}, Buffer, Buffer + (MemSize(Buffer) div SizeOf(TColorBGRA)) {$ENDIF}
);
end;

Expand Down Expand Up @@ -267,7 +275,6 @@ function CountColorsOnTarget(Target: TSimbaTarget; Bounds: TBox; Formula: EColor
SliceResults[Index] := CountColorsOnBuffer(
Formula, Color, Tolerance, Multipliers,
@Buffer[Lo * BufferWidth], BufferWidth, Bounds.Width, (Hi - Lo) + 1
{$IFDEF SIMBA_BUFFERCHECKS}, Buffer, Buffer + (MemSize(Buffer) div SizeOf(TColorBGRA)) {$ENDIF}
);
end;

Expand Down Expand Up @@ -298,21 +305,24 @@ function CountColorsOnTarget(Target: TSimbaTarget; Bounds: TBox; Formula: EColor
end;

function MatchColorsOnBuffer(Formula: EColorSpace; Color: TColor; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer {$IFDEF SIMBA_BUFFERCHECKS}; BufferLo, BufferHi: PColorBGRA{$ENDIF}): TSingleMatrix;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer): TSingleMatrix;

{$DEFINE MACRO_FINDCOLORS_BEGIN :=
Result.SetSize(SearchWidth, SearchHeight);
}
{$DEFINE MACRO_FINDCOLORS_COMPARE :=
Result[Y, X] := 1 - Cache.Dist;
}
{$DEFINE MACRO_FINDCOLORS_ROW :=
// Nothing
}
{$DEFINE MACRO_FINDCOLORS_END :=
// Nothing
}
MACRO_FINDCOLORS

function MatchColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
Formula: EColorSpace; Color: TColor; Multipliers: TChannelMultipliers): TSingleMatrix;
Formula: EColorSpace; Color: TColor; Multipliers: TChannelMultipliers): TSingleMatrix;
var
Buffer: PColorBGRA;
BufferWidth: Integer;
Expand All @@ -324,7 +334,6 @@ function MatchColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
SliceResults[Index] := MatchColorsOnBuffer(
Formula, Color, Multipliers,
@Buffer[Lo * BufferWidth], BufferWidth, Bounds.Width, (Hi - Lo) + 1
{$IFDEF SIMBA_BUFFERCHECKS}, Buffer, Buffer + (MemSize(Buffer) div SizeOf(TColorBGRA)) {$ENDIF}
);
end;

Expand Down Expand Up @@ -354,6 +363,66 @@ function MatchColorsOnTarget(Target: TSimbaTarget; Bounds: TBox;
end;
end;

procedure HasColorOnBuffer(Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers;
Buffer: PColorBGRA; BufferWidth: Integer; SearchWidth, SearchHeight: Integer;
var Limit: TSimpleThreadsafeLimit);

{$DEFINE MACRO_FINDCOLORS_BEGIN :=
// Nothing
}
{$DEFINE MACRO_FINDCOLORS_COMPARE :=
if (Cache.Dist <= Tolerance) then
Limit.Inc();
}
{$DEFINE MACRO_FINDCOLORS_ROW :=
if Limit.Reached() then Exit;
}
{$DEFINE MACRO_FINDCOLORS_END :=
// Nothing
}
MACRO_FINDCOLORS

function HasColorOnTarget(Target: TSimbaTarget; Bounds: TBox; Formula: EColorSpace; Color: TColor; Tolerance: Single; Multipliers: TChannelMultipliers; MinCount: Integer): Boolean;
var
Buffer: PColorBGRA;
BufferWidth: Integer;

Limit: TSimpleThreadsafeLimit;

procedure Execute(const Index, Lo, Hi: Integer);
begin
HasColorOnBuffer(
Formula, Color, Tolerance, Multipliers,
@Buffer[Lo * BufferWidth], BufferWidth, Bounds.Width, (Hi - Lo) + 1,
Limit
);
end;

var
ThreadsUsed: Integer;
T: Double;
I: Integer;
begin
Limit := TSimpleThreadsafeLimit.Create(Max(MinCount, 1));

if Target.GetImageData(Bounds, Buffer, BufferWidth) then
try
{$IFDEF SIMBA_BENCHMARKS}
T := HighResolutionTime();
{$ENDIF}

ThreadsUsed := SimbaThreadPool.RunParallel(CalculateSlices(Bounds.Width, Bounds.Height), 0, Bounds.Height - 1, @Execute);

{$IFDEF SIMBA_BENCHMARKS}
DebugLn('HasColors: ColorSpace=%s Width=%d Height=%d ThreadsUsed=%d Time=%f', [Formula.AsString(), Bounds.Width, Bounds.Height, ThreadsUsed, HighResolutionTime() - T]);
{$ENDIF}
finally
Target.FreeImageData(Buffer);
end;

Result := Limit.Reached;
end;

initialization
ColorFinderMultithreadOpts.Enabled := True;
ColorFinderMultithreadOpts.SliceWidth := 125;
Expand Down
2 changes: 1 addition & 1 deletion Source/finders/simba.finder_image.pas
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function ConvertBitmapColors(Image: TSimbaImage; ColorSpace: EColorSpace): PByte
for I := 0 to (Image.Width * Image.Height) - 1 do
begin
PBoolean(Dest)^ := Source^.A = 0;
//PBoolean(Dest)^ := (Image.TransparentColorActive and Source^.EqualsIgnoreAlpha(Image.TransparentRGB));

if not PBoolean(Dest)^ then
begin
DestFix := Dest + 1; // temp fix, https://gitlab.com/freepascal.org/fpc/source/-/commit/851af5033fb80d4e19c4a7b5c44d50a36f456374
Expand Down
2 changes: 1 addition & 1 deletion Source/package/simba.package_form.lfm
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object SimbaPackageForm: TSimbaPackageForm
OnShow = FormShow
Position = poMainFormCenter
ShowInTaskBar = stAlways
LCLVersion = '3.0.0.2'
LCLVersion = '3.0.0.3'
object Notebook1: TNotebook
Left = 0
Height = 613
Expand Down
39 changes: 29 additions & 10 deletions Source/script/imports/simba.import_finder.pas
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ procedure _LapeFinder_FindDTMRotated(const Params: PParamArray; const Result: Po
(*
TFinder.FindImageEx
-------------------
> function TFinder.FindImageEx(Bitmap: TImage; Tolerance: Single; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray;
> function TFinder.FindImageEx(Image: TImage; Tolerance: Single; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray;
*)
procedure _LapeFinder_FindImageEx1(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
Expand All @@ -112,7 +112,7 @@ procedure _LapeFinder_FindImageEx1(const Params: PParamArray; const Result: Poin
(*
TFinder.FindImageEx
-------------------
> function TFinder.FindImageEx(Bitmap: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray;
> function TFinder.FindImageEx(Image: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray;
*)
procedure _LapeFinder_FindImageEx2(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
Expand All @@ -122,7 +122,7 @@ procedure _LapeFinder_FindImageEx2(const Params: PParamArray; const Result: Poin
(*
TFinder.FindImage
-----------------
> function TFinder.FindImage(Bitmap: TImage; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
> function TFinder.FindImage(Image: TImage; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
*)
procedure _LapeFinder_FindImage1(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
Expand All @@ -132,7 +132,7 @@ procedure _LapeFinder_FindImage1(const Params: PParamArray; const Result: Pointe
(*
TFinder.FindImage
-----------------
> function TFinder.FindImage(Bitmap: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
> function TFinder.FindImage(Image: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
*)
procedure _LapeFinder_FindImage2(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
Expand Down Expand Up @@ -209,6 +209,21 @@ procedure _LapeFinder_CountColor3(const Params: PParamArray; const Result: Point
PInteger(Result)^ := PSimbaFinder(Params^[0])^.CountColor(PColorTolerance(Params^[1])^, PBox(Params^[2])^);
end;

procedure _LapeFinder_HasColor1(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PSimbaFinder(Params^[0])^.HasColor(PColor(Params^[1])^, PSingle(Params^[2])^, PColorSpace(Params^[3])^, PChannelMultipliers(Params^[4])^, PInteger(Params^[5])^, PBox(Params^[6])^);
end;

procedure _LapeFinder_HasColor2(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PSimbaFinder(Params^[0])^.HasColor(PColor(Params^[1])^, PSingle(Params^[2])^, PInteger(Params^[3])^, PBox(Params^[4])^);
end;

procedure _LapeFinder_HasColor3(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
PBoolean(Result)^ := PSimbaFinder(Params^[0])^.HasColor(PColorTolerance(Params^[1])^, PInteger(Params^[2])^, PBox(Params^[3])^);
end;

(*
TFinder.GetColor
----------------
Expand Down Expand Up @@ -312,7 +327,7 @@ procedure _LapeFinder_PeakBrightness(const Params: PParamArray; const Result: Po
(*
TFinder.FindTemplate
--------------------
> function TFinder.FindTemplate(Bitmap: TImage; MinMatch: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
> function TFinder.FindTemplate(Image: TImage; MinMatch: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint;
*)
procedure _LapeFinder_FindTemplate(const Params: PParamArray; const Result: Pointer); LAPE_WRAPPER_CALLING_CONV
begin
Expand Down Expand Up @@ -387,19 +402,23 @@ procedure ImportFinder(Compiler: TSimbaScript_Compiler);
addFinderMethod('function TFinder.FindDTM(DTM: TDTM; Bounds: TBox = [-1,-1,-1,-1]): TPoint', @_LapeFinder_FindDTM);
addFinderMethod('function TFinder.FindDTMRotated(DTM: TDTM; StartDegrees, EndDegrees: Double; Step: Double; out FoundDegrees: TDoubleArray; Bounds: TBox = [-1,-1,-1,-1]): TPoint', @_LapeFinder_FindDTMRotated);

addFinderMethod('function TFinder.FindImageEx(Bitmap: TImage; Tolerance: Single; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindImageEx1);
addFinderMethod('function TFinder.FindImageEx(Bitmap: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindImageEx2);
addFinderMethod('function TFinder.FindImage(Bitmap: TImage; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint; overload', @_LapeFinder_FindImage1);
addFinderMethod('function TFinder.FindImage(Bitmap: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TPoint; overload', @_LapeFinder_FindImage2);
addFinderMethod('function TFinder.FindImageEx(Image: TImage; Tolerance: Single; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindImageEx1);
addFinderMethod('function TFinder.FindImageEx(Image: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; MaxToFind: Integer = -1; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindImageEx2);
addFinderMethod('function TFinder.FindImage(Image: TImage; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint; overload', @_LapeFinder_FindImage1);
addFinderMethod('function TFinder.FindImage(Image: TImage; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TPoint; overload', @_LapeFinder_FindImage2);

addFinderMethod('function TFinder.FindTemplate(Bitmap: TImage; MinMatch: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint', @_LapeFinder_FindTemplate);
addFinderMethod('function TFinder.FindTemplate(Image: TImage; MinMatch: Single; Bounds: TBox = [-1,-1,-1,-1]): TPoint', @_LapeFinder_FindTemplate);

addFinderMethod('function TFinder.MatchColor(Color: TColor; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TSingleMatrix', @_LapeFinder_MatchColor);

addFinderMethod('function TFinder.FindColor(Color: TColor; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindColor1);
addFinderMethod('function TFinder.FindColor(Color: TColor; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindColor2);
addFinderMethod('function TFinder.FindColor(Color: TColorTolerance; Bounds: TBox = [-1,-1,-1,-1]): TPointArray; overload', @_LapeFinder_FindColor3);

addFinderMethod('function TFinder.HasColor(Color: TColor; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; MinCount: Integer = 1; Bounds: TBox = [-1,-1,-1,-1]): Boolean; overload', @_LapeFinder_HasColor1);
addFinderMethod('function TFinder.HasColor(Color: TColor; Tolerance: Single; MinCount: Integer = 1; Bounds: TBox = [-1,-1,-1,-1]): Boolean; overload', @_LapeFinder_HasColor2);
addFinderMethod('function TFinder.HasColor(Color: TColorTolerance; MinCount: Integer = 1; Bounds: TBox = [-1,-1,-1,-1]): Boolean; overload;', @_LapeFinder_HasColor3);

addFinderMethod('function TFinder.CountColor(Color: TColor; Tolerance: Single; Bounds: TBox = [-1,-1,-1,-1]): Integer; overload;', @_LapeFinder_CountColor1);
addFinderMethod('function TFinder.CountColor(Color: TColor; Tolerance: Single; ColorSpace: EColorSpace; Multipliers: TChannelMultipliers; Bounds: TBox = [-1,-1,-1,-1]): Integer; overload;', @_LapeFinder_CountColor2);
addFinderMethod('function TFinder.CountColor(Color: TColorTolerance; Bounds: TBox = [-1,-1,-1,-1]): Integer; overload;', @_LapeFinder_CountColor3);
Expand Down
Loading

0 comments on commit 9cf7444

Please sign in to comment.