From 9415d0810088c37e7f0f79e2a31c7e723bd6152c Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 13 Jun 2011 17:41:06 +0200 Subject: [PATCH 01/37] Finder: Trying a different CTS approach. --- Units/MMLCore/finder.pas | 98 ++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index d9eef25..094f357 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -124,7 +124,7 @@ begin; if (startx >= x1) and (startx <= x2) and (starty >= y1) and (starty <= y2) then begin; ClientTPA[c] := Point(Startx, StartY); - inc(c); + Inc(c); end; Repeat if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y1 >= y1) and (Currbox.y1 <= y2) then @@ -132,35 +132,36 @@ begin; if (I >= x1) and ( I <= x2) then begin; ClientTPA[c] := Point(i,CurrBox.y1); - inc(c); + Inc(c); end; if (CurrBox.x2 >= x1) and (CurrBox.x2 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.y1 + 1 to CurrBox.y2 do if (I >= y1) and ( I <= y2) then begin; ClientTPA[c] := Point(Currbox.x2, I); - inc(c); + Inc(c); end; if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y2 <= y2) then for i := CurrBox.x2 - 1 downto CurrBox.x1 do if (I >= x1) and ( I <= x2) then begin; ClientTPA[c] := Point(i,CurrBox.y2); - inc(c); + Inc(c); end; if (CurrBox.x1 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.y2 - 1 downto CurrBox.y1 do if (I >= y1) and ( I <= y2) then begin; ClientTPA[c] := Point(Currbox.x1, I); - inc(c); + Inc(c); end; - inc(ring); + Inc(ring); CurrBox.x1 := Startx-ring; CurrBox.y1 := Starty-Ring; CurrBox.x2 := Startx+Ring; CurrBox.y2 := Starty+Ring; - until (Currbox.x1 < x1) and (Currbox.x2 > x2) and (currbox.y1 < y1) and (currbox.y2 > y2); + until (Currbox.x1 < x1) and (Currbox.x2 > x2) and (currbox.y1 < y1) + and (currbox.y2 > y2); end; function CalculateRowPtrs(ReturnData : TRetData; RowCount : integer) : TPRGB32Array;overload; @@ -176,6 +177,7 @@ function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array;overload; begin Result := Bitmap.RowPtrs; end; + //SkipCoords[y][x] = False/True; True means its "transparent" and therefore not needed to be checked. procedure CalculateBitmapSkipCoords(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray); var @@ -200,7 +202,9 @@ begin; inc(ptr); end; end; -//Points left holds the amount of points that are "left" to be checked (Including the point itself.. So for example Pointsleft[0][0] would hold the total amount of pixels that are to be checked. +{ Points left holds the amount of points that are "left" to be checked + (Including the point itself.. So for example Pointsleft[0][0] would + hold the total amount of pixels that are to be checked. } procedure CalculateBitmapSkipCoordsEx(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray;out TotalPoints : integer; out PointsLeft : T2DIntArray); var x,y : integer; @@ -239,6 +243,7 @@ begin; end; end; +{ Initialise the variables for TMFinder } constructor TMFinder.Create(aClient: TObject); var I : integer; @@ -570,10 +575,51 @@ var PtrData: TRetData; RowData : TPRGB32Array; dX, dY, clR, clG, clB,i,Hispiral: Integer; - H1, S1, L1, H2, S2, L2: Extended; - HueXTol, SatXTol: Extended; label Hit; + function cts0: integer; + var j: integer; + begin + for j := 0 to HiSpiral do + if ((abs(clB-RowData[ClientTPA[j].y][ClientTPA[j].x].B) <= Tol) and + (abs(clG-RowData[ClientTPA[j].y][ClientTPA[j].x].G) <= Tol) and + (Abs(clR-RowData[ClientTPA[j].y][ClientTPA[j].x].R) <= Tol)) then + exit(j); + exit(-1); + end; + + function cts1: integer; + var j: integer; + begin + Tol := Sqr(Tol); + for j := 0 to HiSpiral do + if (sqr(clB - RowData[ClientTPA[j].y][ClientTPA[j].x].B) + + sqr(clG - RowData[ClientTPA[j].y][ClientTPA[j].x].G) + + sqr(clR-RowData[ClientTPA[j].y][ClientTPA[j].x].R)) <= Tol then + exit(j); + exit(-1); + end; + + function cts2: integer; + var j: integer; + HueXTol, SatXTol: Extended; + H1, S1, L1, H2, S2, L2: Extended; + begin + RGBToHSL(clR,clG,clB,H1,S1,L1); + HueXTol := hueMod * Tol; + SatXTol := satMod * Tol; + for j := 0 to HiSpiral do + begin + RGBToHSL(RowData[ClientTPA[j].y][ClientTPA[j].x].R, + RowData[ClientTPA[j].y][ClientTPA[j].x].G, + RowData[ClientTPA[j].y][ClientTPA[j].x].B,H2,S2,L2); + if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then + exit(j); + end; + + exit(-1); + end; + begin Result := false; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) @@ -584,8 +630,6 @@ begin dY := ye - ys; //next, convert the color to r,g,b ColorToRGB(Color, clR, clG, clB); - if Cts = 2 then - RGBToHSL(clR,clG,clB,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); //Load rowdata @@ -595,34 +639,22 @@ begin HiSpiral := (dy+1) * (dx + 1) -1; case CTS of 0: - for i := 0 to HiSpiral do - if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tol) and - (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tol) and - (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tol)) then - goto Hit; + begin + i := cts0(); + if i <> -1 then + goto Hit; + end; 1: begin - Tol := Sqr(Tol); - for i := 0 to HiSpiral do - if (sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B) + - sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + - sqr(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R)) <= Tol then - goto Hit; + i := cts1(); + if i <> -1 then + goto Hit; end; + 2: { Can be optimized a lot... RGBToHSL isn't really inline, } begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for i := 0 to HiSpiral do - begin - RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, - RowData[ClientTPA[i].y][ClientTPA[i].x].G, - RowData[ClientTPA[i].y][ClientTPA[i].x].B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - goto Hit; - end; end; end; Result := False; From b87a123701fb192b2f31efb8896d7e661b399c32 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 13 Jun 2011 17:44:04 +0200 Subject: [PATCH 02/37] More cleanups to CTS. --- Units/MMLCore/finder.pas | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 094f357..e846b08 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -639,24 +639,15 @@ begin HiSpiral := (dy+1) * (dx + 1) -1; case CTS of 0: - begin i := cts0(); - if i <> -1 then - goto Hit; - end; - 1: - begin i := cts1(); - if i <> -1 then - goto Hit; - end; - 2: - { Can be optimized a lot... RGBToHSL isn't really inline, } - begin - end; + i := cts2(); end; + if i <> -1 then + goto Hit; + Result := False; TClient(Client).IOManager.FreeReturnData; Exit; From 14474a84ab69e15a1de3998dc01cb3053daba384 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 13 Jun 2011 18:16:59 +0200 Subject: [PATCH 03/37] CTS rework for FindColorsTolerance. --- Units/MMLCore/finder.pas | 153 ++++++++++++++++++++++----------------- 1 file changed, 85 insertions(+), 68 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index e846b08..5a792f8 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -333,6 +333,14 @@ begin end; end; +function ColorSameCTS2(Tolerance: Integer; H1,S1,L1,H2,S2,L2, hueMod, satMod: extended): + boolean; inline; +begin + result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and + (abs(S2-S1) <= (satMod * Tolerance)) + and (abs(L1-L2) <= Tolerance)); +end; + procedure TMFinder.UpdateCachedValues(NewWidth, NewHeight: integer); begin CachedWidth := NewWidth; @@ -575,7 +583,6 @@ var PtrData: TRetData; RowData : TPRGB32Array; dX, dY, clR, clG, clB,i,Hispiral: Integer; - label Hit; function cts0: integer; var j: integer; @@ -638,25 +645,22 @@ begin LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); HiSpiral := (dy+1) * (dx + 1) -1; case CTS of - 0: - i := cts0(); - 1: - i := cts1(); - 2: - i := cts2(); + 0: i := cts0(); + 1: i := cts1(); + 2: i := cts2(); end; - if i <> -1 then - goto Hit; - - Result := False; - TClient(Client).IOManager.FreeReturnData; - Exit; - - Hit: + if i = -1 then + begin + Result := False; + TClient(Client).IOManager.FreeReturnData; + Exit; + end else + begin Result := True; x := ClientTPA[i].x + xs; y := ClientTPA[i].y + ys; TClient(Client).IOManager.FreeReturnData; + end; end; function TMFinder.FindColoredArea(var x, y: Integer; Color, xs, ys, xe, ye, MinArea: Integer): Boolean; @@ -1038,8 +1042,69 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc,C: Integer; - dX, dY, clR, clG, clB, xx, yy: Integer; + dX, dY, clR, clG, clB: Integer; H1, S1, L1, H2, S2, L2, hueXTol, satXTol: Extended; + + procedure cts0; + var xx, yy: integer; + begin + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then + begin; + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + inc(c); + end; + inc(Ptr); + end; + Inc(Ptr, PtrInc); + end; + end; + + + procedure cts1; + var xx, yy: integer; + begin + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then + begin; + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + inc(c); + end; + inc(ptr); + end; + Inc(Ptr, PtrInc); + end; + end; + + procedure cts2; + var xx, yy: integer; + begin + HueXTol := hueMod * Tol; + SatXTol := satMod * Tol; + for yy := ys to ye do + begin + for xx := xs to xe do + begin + RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); + if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then + begin; + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + Inc(c); + end; + Inc(Ptr) + end; + Inc(Ptr, PtrInc); + end; + end; begin Result := false; DefaultOperations(xs,ys,xe,ye); @@ -1059,64 +1124,16 @@ begin PtrInc := PtrData.IncPtrWith; c := 0; case CTS of - 0: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - - 1: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - - 2: - begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - Inc(c); - end; - Inc(Ptr) - end; - Inc(Ptr, PtrInc); - end; - end; + 0: cts0(); + 1: cts1(); + 2: cts2(); end; SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; TClient(Client).IOManager.FreeReturnData; end; + function TMFinder.FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; var From 7a412d16704f270ba44674c8422e1272c8994b11 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 13 Jun 2011 20:21:23 +0200 Subject: [PATCH 04/37] CTS: Cleanups. --- Units/MMLCore/finder.pas | 153 +++++++++++++++++++-------------------- 1 file changed, 74 insertions(+), 79 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 5a792f8..f6ba121 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -30,14 +30,12 @@ interface {$define CheckAllBackground}//Undefine this to only check the first white point against the background (in masks). uses - colour_conv, Classes, SysUtils,bitmaps,MufasaBase,DTM, MufasaTypes; // Types + colour_conv, Classes, SysUtils, bitmaps, DTM, MufasaTypes; // Types { TMFinder Class } { - Should be 100% OS independant, - as all OS dependant code is in the IO Manager - + Should be 100% OS independant, as all OS dependant code is in the IO Manager. Let's try not to use any OS-specific defines here? ;) } @@ -101,19 +99,16 @@ type implementation uses -// colour_conv,// For RGBToColor, etc. - Client, // For the Client Casts. - math, //min/max - mmath, - tpa, //TPABounds - dtmutil - ; + Client, // For the Client casting. + math, // min/max + tpa, //TPABounds + dtmutil; procedure TMFinder.LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer); var i,c,Ring : integer; CurrBox : TBox; -begin; +begin i := 0; Ring := 1; c := 0; @@ -126,7 +121,7 @@ begin; ClientTPA[c] := Point(Startx, StartY); Inc(c); end; - Repeat + repeat if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y1 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.x1 + 1 to CurrBox.x2 do if (I >= x1) and ( I <= x2) then @@ -164,16 +159,16 @@ begin; and (currbox.y2 > y2); end; -function CalculateRowPtrs(ReturnData : TRetData; RowCount : integer) : TPRGB32Array;overload; +function CalculateRowPtrs(ReturnData: TRetData; RowCount: integer) : TPRGB32Array; overload; var I : integer; begin; - setlength(result,RowCount); + SetLength(result,RowCount); for i := 0 to RowCount - 1 do result[i] := ReturnData.Ptr + ReturnData.RowLen * i; end; -function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array;overload; +function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array; overload; begin Result := Bitmap.RowPtrs; end; @@ -1039,72 +1034,74 @@ end; function TMFinder.FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; var - PtrData: TRetData; - Ptr: PRGB32; - PtrInc,C: Integer; - dX, dY, clR, clG, clB: Integer; - H1, S1, L1, H2, S2, L2, hueXTol, satXTol: Extended; + PtrData: TRetData; + Ptr: PRGB32; + PtrInc,C: Integer; + dX, dY, clR, clG, clB: Integer; - procedure cts0; - var xx, yy: integer; - begin - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - end; - - - procedure cts1; - var xx, yy: integer; - begin - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - end; - - procedure cts2; - var xx, yy: integer; - begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then + procedure cts0; + var xx, yy: integer; + begin + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then begin; ClientTPA[c].x := xx; ClientTPA[c].y := yy; - Inc(c); + inc(c); end; - Inc(Ptr) - end; - Inc(Ptr, PtrInc); - end; - end; + inc(Ptr); + end; + Inc(Ptr, PtrInc); + end; + end; + + + procedure cts1; + var xx, yy: integer; + begin + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then + begin; + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + inc(c); + end; + inc(ptr); + end; + Inc(Ptr, PtrInc); + end; + end; + + procedure cts2; + var xx, yy: integer; + H1, S1, L1, H2, S2, L2, hueXTol, satXTol: Extended; + begin + ColorToHSL(color,H1,S1,L1); + HueXTol := hueMod * Tol; + SatXTol := satMod * Tol; + for yy := ys to ye do + begin + for xx := xs to xe do + begin + RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); + if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then + begin; + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + Inc(c); + end; + Inc(Ptr) + end; + Inc(Ptr, PtrInc); + end; + end; + begin Result := false; DefaultOperations(xs,ys,xe,ye); @@ -1113,8 +1110,6 @@ begin dY := ye - ys; //next, convert the color to r,g,b ColorToRGB(Color, clR, clG, clB); - if CTS = 2 then - ColorToHSL(color,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); From 5bf7d8beeaf69133b03a3f8c04124f33dea4e24c Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 13 Jun 2011 20:38:00 +0200 Subject: [PATCH 05/37] Completed first CTS rework. --- Units/MMLCore/finder.pas | 135 ++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 59 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index f6ba121..43b3138 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -870,10 +870,68 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc: Integer; - dX, dY, clR, clG, clB, xx, yy: Integer; - H1, S1, L1, H2, S2, L2: Extended; - HueXTol, SatXTol: Extended; - label Hit; + dX, dY, clR, clG, clB: Integer; + xy: TPoint; + + function cts0: tpoint; + var xx, yy: integer; + begin + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and + (Abs(clR-Ptr^.R) <= Tol)) then + exit(Point(xx, yy)); + inc(Ptr); + end; + Inc(Ptr, PtrInc); + end; + + result.x := -1; result.y := -1; + end; + + function cts1: tpoint; + var xx, yy: integer; + begin + Tol := Sqr(Tol); + + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then + exit(Point(xx, yy)); + inc(ptr); + end; + Inc(Ptr, PtrInc); + end; + + result.x := -1; result.y := -1; + end; + + function cts2: tpoint; + var xx, yy: integer; + H1, S1, L1, H2, S2, L2: Extended; + HueXTol, SatXTol: Extended; + begin + RGBToHSL(clR,clG,clB,H1,S1,L1); + HueXTol := hueMod * Tol; + SatXTol := satMod * Tol; + for yy := ys to ye do + begin + for xx := xs to xe do + begin + RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); + if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then + exit(Point(xx, yy)); + inc(Ptr); + end; + Inc(Ptr, PtrInc); + end; + + result.x := -1; result.y := -1; + end; begin Result := false; @@ -885,8 +943,6 @@ begin dY := ye - ys; //next, convert the color to r,g,b ColorToRGB(Color, clR, clG, clB); - if Cts = 2 then - RGBToHSL(clR,clG,clB,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -896,61 +952,22 @@ begin PtrInc := PtrData.IncPtrWith; case CTS of - 0: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - goto Hit; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - - 1: - begin - Tol := Sqr(Tol); - - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then - goto Hit; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - - end; - 2: - { Can be optimized a lot... RGBToHSL isn't really inline, } - begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - goto Hit; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - end; + 0: xy := cts0(); + 1: xy := cts1(); + 2: xy := cts2(); end; - Result := False; - TClient(Client).IOManager.FreeReturnData; - Exit; - - Hit: - Result := True; - x := xx; - y := yy; + if (xy.x = -1) and (xy.y = -1) then + begin + Result := False; TClient(Client).IOManager.FreeReturnData; + Exit; + end else + begin + Result := True; + x := xy.x; + y := xy.y; + TClient(Client).IOManager.FreeReturnData; + end; end; function TMFinder.FindColoredAreaTolerance(var x, y: Integer; Color, xs, ys, xe, ye, MinArea, tol: Integer): Boolean; From 91d952d33ab9b8ddcb76bed991a1ea0c5907e084 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 16 Jun 2011 12:52:10 +0200 Subject: [PATCH 06/37] CTS cleanups. --- Units/MMLCore/finder.pas | 112 +++++++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 47 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 43b3138..6b51ddc 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -328,6 +328,14 @@ begin end; end; +{ + TODO: See if this is actually inlined. If it is, we can shorten the + subprocedures; if it is not, either: + - Paste a lot of code. + - Pass a record of the required data to prevent pushing arguments on the + stack. +} + function ColorSameCTS2(Tolerance: Integer; H1,S1,L1,H2,S2,L2, hueMod, satMod: extended): boolean; inline; begin @@ -1280,11 +1288,60 @@ function TMFinder.FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer ): boolean; var - PtrData: TRetData; - c : integer; - RowData : TPRGB32Array; - dX, dY, clR, clG, clB, i,SpiralHi: Integer; - H1, S1, L1, H2, S2, L2, HueXTol, SatXTol: Extended; + PtrData: TRetData; + c : integer; + RowData : TPRGB32Array; + dX, dY, clR, clG, clB, i,SpiralHi: Integer; + + procedure cts0; + var i: integer; + begin + for i := 0 to SpiralHi do + if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tolerance) and + (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tolerance) and + (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tolerance)) then + begin; + ClientTPA[c].x := ClientTPA[i].x + xs; + ClientTPA[c].y := ClientTPA[i].y + ys; + inc(c); + end; + end; + + procedure cts1; + var i: integer; + begin + for i := 0 to SpiralHi do + if (Sqrt(sqr(clR - RowData[ClientTPA[i].y][ClientTPA[i].x].R) + + sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + + sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B)) <= Tolerance) then + begin; + ClientTPA[c].x := ClientTPA[i].x + xs; + ClientTPA[c].y := ClientTPA[i].y + ys; + inc(c); + end; + end; + + procedure cts2; + var i: integer; + H1, S1, L1, H2, S2, L2, HueXTol, SatXTol: Extended; + begin + ColorToHSL(Color, H1, S1, L1); + HueXTol := hueMod * Tolerance; + SatXTol := satMod * Tolerance; + for i := 0 to SpiralHi do + begin; + RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, + RowData[ClientTPA[i].y][ClientTPA[i].x].G, + RowData[ClientTPA[i].y][ClientTPA[i].x].B, + H2,S2,L2); + if ((abs(H1 - H2) <= (HueXTol)) and (abs(S1 - S2) <= (satXTol)) and (abs(L1 - L2) <= Tolerance)) then + begin; + ClientTPA[c].x := ClientTPA[i].x + xs; + ClientTPA[c].y := ClientTPA[i].y + ys; + inc(c); + end; + end; + end; begin Result := false; DefaultOperations(xs,ys,xe,ye); @@ -1293,7 +1350,6 @@ begin dY := ye - ys; //next, convert the color to r,g,b ColorToRGB(Color, clR, clG, clB); - ColorToHSL(Color, H1, S1, L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -1305,47 +1361,9 @@ begin LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); SpiralHi := (dx + 1) * (dy + 1) - 1; case CTS of - 0: - for i := 0 to SpiralHi do - if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tolerance) and - (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tolerance) and - (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - - - 1: - for i := 0 to SpiralHi do - if (Sqrt(sqr(clR - RowData[ClientTPA[i].y][ClientTPA[i].x].R) + - sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + - sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B)) <= Tolerance) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - - 2: - begin; - HueXTol := hueMod * Tolerance; - SatXTol := satMod * Tolerance; - for i := 0 to SpiralHi do - begin; - RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, - RowData[ClientTPA[i].y][ClientTPA[i].x].G, - RowData[ClientTPA[i].y][ClientTPA[i].x].B, - H2,S2,L2); - if ((abs(H1 - H2) <= (HueXTol)) and (abs(S1 - S2) <= (satXTol)) and (abs(L1 - L2) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - end; - end; + 0: cts0(); + 1: cts1(); + 2: cts2(); end; SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); From 58ea6021cd0cee3bd54f8ce93713bedc9ff3feb4 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 16 Jun 2011 14:26:20 +0200 Subject: [PATCH 07/37] CTS work. CTS 2 is still broken for bitmaps. --- Tests/PS/BmpBenchmark.simba | 25 +++++ Units/MMLCore/bitmaps.pas | 20 +++- Units/MMLCore/finder.pas | 178 +++++++++++++++++++++++++--------- Units/MMLCore/mufasatypes.pas | 8 ++ 4 files changed, 186 insertions(+), 45 deletions(-) create mode 100644 Tests/PS/BmpBenchmark.simba diff --git a/Tests/PS/BmpBenchmark.simba b/Tests/PS/BmpBenchmark.simba new file mode 100644 index 0000000..5bf5551 --- /dev/null +++ b/Tests/PS/BmpBenchmark.simba @@ -0,0 +1,25 @@ +program new; +//http://farm4.static.flickr.com/3067/2612399892_7df428d482.jpg +{Make the above bitmap your target} +var + Bmp : integer; + x,y : integer; + w,h : integer; + t, i: integer; +begin + Bmp := createBitmap(15, 10); + FastDrawClear(bmp, clwhite); + GetClientDimensions(w,h); + + setcolortolerancespeed(2); + t:=getsystemtime; + for i := 0 to 10 do + FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,500); + writeln((getsystemtime-t) / 10.0); + + if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,500) then + begin + writeln('found'); + MoveMouse(x,y); + end; +end. diff --git a/Units/MMLCore/bitmaps.pas b/Units/MMLCore/bitmaps.pas index 335550f..f04effa 100644 --- a/Units/MMLCore/bitmaps.pas +++ b/Units/MMLCore/bitmaps.pas @@ -64,6 +64,7 @@ type function FastGetPixel(x,y : integer) : TColor; function FastGetPixels(Points : TPointArray) : TIntegerArray; function GetAreaColors(xs,ys,xe,ye : integer) : T2DIntArray; + function GetHSLValues(xs, ys, xe, ye: integer): T2DHSLArray; procedure FastDrawClear(Color : TColor); procedure FastDrawTransparent(x, y: Integer; TargetBitmap: TMufasaBitmap); procedure FastReplaceColor(OldColor, NewColor: TColor); @@ -876,6 +877,23 @@ begin result[x-xs][y-ys] := BGRToRGB(FData[y*w+x]); end; +function TMufasaBitmap.GetHSLValues(xs, ys, xe, ye: integer): T2DHSLArray; +var + x, y: integer; + R, G, B, C: integer; +begin + ValidatePoint(xs,ys); + ValidatePoint(xe,ye); + setlength(result,xe-xs+1,ye-ys+1); + for y := ys to ye do + for x := xs to xe do + begin + RGBToHSL(FData[y*w+x].R, FData[y*w+x].G, FData[y*w+x].B, + Result[x-xs][y-ys].H, Result[x-xs][y-ys].S, + Result[x-xs][y-ys].L); + end; +end; + procedure TMufasaBitmap.SetTransparentColor(Col: TColor); begin self.FTransparentSet:= True; @@ -1406,7 +1424,7 @@ var i,minw,minh : integer; begin if (AWidth <> w) or (AHeight <> h) then - begin; + begin if AWidth*AHeight <> 0 then begin; NewData := GetMem(AWidth * AHeight * SizeOf(TRGB32)); diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 6b51ddc..d54af95 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -37,6 +37,9 @@ uses { Should be 100% OS independant, as all OS dependant code is in the IO Manager. Let's try not to use any OS-specific defines here? ;) + + + Benchmarks with FindBitmapToleranceIn on _very_ high tolerance! } type @@ -336,7 +339,21 @@ end; stack. } -function ColorSameCTS2(Tolerance: Integer; H1,S1,L1,H2,S2,L2, hueMod, satMod: extended): +{ Not using var for each arg now, as it should be inlined } +function ColorSame_cts0(Tolerance : Integer; R1,G1,B1,R2,G2,B2 : byte) : boolean; inline; + +begin + Result := ((Abs(R1-R2) <= Tolerance) and (Abs(G1-G2) <= Tolerance) and (Abs(B1-B2) <= Tolerance)); +end; + +{ Not using var for each arg now, as it should be inlined } +function ColorSame_cts1(Tolerance : Integer; R1,G1,B1,R2,G2,B2 : byte) : boolean; inline; + +begin + Result := (Sqrt(sqr(R1-R2) + sqr(G1-G2) + sqr(B1-B2)) <= Tolerance); +end; + +function ColorSame_cts2(Tolerance: Integer; H1,S1,L1,H2,S2,L2, hueMod, satMod: extended): boolean; inline; begin result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and @@ -896,7 +913,7 @@ var Inc(Ptr, PtrInc); end; - result.x := -1; result.y := -1; + Result := Point(-1, -1); end; function cts1: tpoint; @@ -915,7 +932,7 @@ var Inc(Ptr, PtrInc); end; - result.x := -1; result.y := -1; + Result := Point(-1, -1); end; function cts2: tpoint; @@ -938,7 +955,7 @@ var Inc(Ptr, PtrInc); end; - result.x := -1; result.y := -1; + Result := Point(-1, -1); end; begin @@ -1291,7 +1308,7 @@ var PtrData: TRetData; c : integer; RowData : TPRGB32Array; - dX, dY, clR, clG, clB, i,SpiralHi: Integer; + dX, dY, clR, clG, clB, SpiralHi: Integer; procedure cts0; var i: integer; @@ -1575,21 +1592,106 @@ end; function TMFinder.FindBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean; var - MainRowdata : TPRGB32Array; - BmpRowData : TPRGB32Array; - PtrData : TRetData; - BmpW,BmpH : integer; - xBmp,yBmp : integer; - tmpY : integer; - dX, dY, xx, yy: Integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; - SkipCoords : T2DBoolArray; -label NotFoundBmp; + MainRowdata : TPRGB32Array; + PtrData : TRetData; + BmpW,BmpH : integer; + dX, dY: Integer; + SkipCoords : T2DBoolArray; + foundP: TPoint; + + function cts0: tpoint; + var xx, yy, xBmp, yBmp, tmpY: integer; + BmpRowData : TPRGB32Array; + label NotFoundBmp; + begin + BmpRowData:= CalculateRowPtrs(bitmap); + + for yy := 0 to dY do + for xx := 0 to dX do + begin + for yBmp:= 0 to BmpH do + begin + tmpY := yBmp + yy; + for xBmp := 0 to BmpW do + if not SkipCoords[yBmp][xBmp] then + if not ColorSame_cts0(Tolerance, + BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, + MainRowdata[tmpY][xBmp + xx].R, + MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B) then + goto NotFoundBmp; + end; + exit(Point(xx + xs, yy + ys)); + NotFoundBmp: // double break + end; + + Result := Point(-1, -1); + end; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } + function cts1: tpoint; + var xx, yy, xBmp, yBmp, tmpY: integer; + BmpRowData : TPRGB32Array; + label NotFoundBmp; + begin + BmpRowData:= CalculateRowPtrs(bitmap); + + for yy := 0 to dY do + for xx := 0 to dX do + begin + for yBmp:= 0 to BmpH do + begin + tmpY := yBmp + yy; + for xBmp := 0 to BmpW do + if not SkipCoords[yBmp][xBmp] then + if not ColorSame_cts1(Tolerance, + BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, + MainRowdata[tmpY][xBmp + xx].R, + MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B) then + goto NotFoundBmp; + end; + exit(Point(xx + xs, yy + ys)); + NotFoundBmp: // double break + end; + + Result := Point(-1, -1); + end; + + function cts2: tpoint; + var H1, S1, L1, H2, S2, L2, HMod, SMod: extended; + xx, yy, xBmp, yBmp, tmpY: integer; + + HSLRows: T2DHSLArray; + + label NotFoundBmp; + begin + HSLRows := bitmap.GetHSLValues(0, 0, BmpW - 1, BmpH - 1); + + for yy := 0 to dY do + for xx := 0 to dX do + begin + for yBmp:= 0 to BmpH do + begin + tmpY := yBmp + yy; + for xBmp := 0 to BmpW do + if not SkipCoords[yBmp][xBmp] then + begin + RGBToHSL(MainRowdata[tmpY][xBmp + xx].R, MainRowdata[tmpY][xBmp + xx].G, + MainRowdata[tmpY][xBmp + xx].B, H2, S2, L2); + + if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, + H2, S2, L2, hueMod, satMod) then + goto NotFoundBmp; + end; + end; + exit(Point(xx + xs, yy + ys)); + NotFoundBmp: // double break + end; + + Result := Point(-1, -1); + end; + begin - Result := false; + Result := False; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) DefaultOperations(xs,ys,xe,ye); @@ -1600,43 +1702,31 @@ begin PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); //Caculate the row ptrs MainRowdata:= CalculateRowPtrs(PtrData,dy+1); - BmpRowData:= CalculateRowPtrs(bitmap); + + //Get the 'fixed' bmp size BmpW := bitmap.Width - 1; BmpH := bitmap.Height - 1; //Heck our bitmap cannot be outside the search area dX := dX - bmpW; dY := dY - bmpH; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - - CCTS := Self.CTS; //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); - for yy := 0 to dY do - for xx := 0 to dX do - begin; - for yBmp:= 0 to BmpH do - begin; - tmpY := yBmp + yy; - for xBmp := 0 to BmpW do - if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, - H,S,L,HMod,SMod) then - goto NotFoundBmp; - end; - //We did find the Bmp, otherwise we would be at the part below - TClient(Client).IOManager.FreeReturnData; - x := xx + xs; - y := yy + ys; - result := true; - exit; - NotFoundBmp: - end; + case Self.CTS of + 0: foundP := cts0(); + 1: foundP := cts1(); + 2: foundP := cts2(); + end; + + if (foundP.x = -1) and (foundP.y = -1) then + result := False + else begin + x := foundP.x; + y := foundP.y; + Result := True; + end; TClient(Client).IOManager.FreeReturnData; end; diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index ef1adea..a5e4cf2 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -60,6 +60,14 @@ type TRGB32Array = array of TRGB32; TPRGB32Array = array of PRGB32; //Array of Pointers + THSL = record + H, S, L: extended; + end; + PHSL = ^THSL; + + THSLArray = array of THSL; + T2DHSLArray = array of array of THSL; + TRetData = record Ptr : PRGB32; IncPtrWith : integer; From 2e1e786d0ece69dc3e42fb92106a71dce0faf975 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 16 Jun 2011 15:11:17 +0200 Subject: [PATCH 08/37] FindBitmapToleranceIn now works. --- Units/MMLCore/bitmaps.pas | 8 ++++---- Units/MMLCore/finder.pas | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/Units/MMLCore/bitmaps.pas b/Units/MMLCore/bitmaps.pas index f04effa..80ad422 100644 --- a/Units/MMLCore/bitmaps.pas +++ b/Units/MMLCore/bitmaps.pas @@ -884,13 +884,13 @@ var begin ValidatePoint(xs,ys); ValidatePoint(xe,ye); - setlength(result,xe-xs+1,ye-ys+1); + setlength(result,ye-ys+1,xe-xs+1); for y := ys to ye do for x := xs to xe do - begin + begin { REWRITE THIS } RGBToHSL(FData[y*w+x].R, FData[y*w+x].G, FData[y*w+x].B, - Result[x-xs][y-ys].H, Result[x-xs][y-ys].S, - Result[x-xs][y-ys].L); + Result[y-ys][x-xs].H, Result[y-ys][x-xs].S, + Result[y-ys][x-xs].L); end; end; diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index d54af95..37e1bc0 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -353,12 +353,12 @@ begin Result := (Sqrt(sqr(R1-R2) + sqr(G1-G2) + sqr(B1-B2)) <= Tolerance); end; -function ColorSame_cts2(Tolerance: Integer; H1,S1,L1,H2,S2,L2, hueMod, satMod: extended): +function ColorSame_cts2(Tolerance: Integer; H1, S1, L1, H2,S2,L2, hueMod, satMod: extended): boolean; inline; begin result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and - (abs(S2-S1) <= (satMod * Tolerance)) - and (abs(L1-L2) <= Tolerance)); + (abs(S1 - S2) <= (satMod * Tolerance)) + and (abs(L1 - L2) <= Tolerance)); end; procedure TMFinder.UpdateCachedValues(NewWidth, NewHeight: integer); @@ -1657,14 +1657,14 @@ var end; function cts2: tpoint; - var H1, S1, L1, H2, S2, L2, HMod, SMod: extended; + var H2, S2, L2, HMod, SMod: extended; xx, yy, xBmp, yBmp, tmpY: integer; HSLRows: T2DHSLArray; label NotFoundBmp; begin - HSLRows := bitmap.GetHSLValues(0, 0, BmpW - 1, BmpH - 1); + HSLRows := bitmap.GetHSLValues(0, 0, BmpW, BmpH); for yy := 0 to dY do for xx := 0 to dX do @@ -1678,7 +1678,9 @@ var RGBToHSL(MainRowdata[tmpY][xBmp + xx].R, MainRowdata[tmpY][xBmp + xx].G, MainRowdata[tmpY][xBmp + xx].B, H2, S2, L2); - if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, + if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, + HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, + //if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, H2, S2, L2, hueMod, satMod) then goto NotFoundBmp; end; From 7a0db25416639e76234b239a854b510e2043a91b Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sun, 5 Jun 2011 19:44:52 +0200 Subject: [PATCH 09/37] Add L*a*b CTS (3). --- Projects/Simba/Simba.res | Bin 19212 -> 19864 bytes Units/MMLCore/colour_conv.pas | 52 +++++++++++++++++++++++++++++++++- Units/MMLCore/finder.pas | 29 ++++++++++++++++++- 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/Projects/Simba/Simba.res b/Projects/Simba/Simba.res index 42c7633aefc517e477597f5189923c1d3ac6b5ad..0087bd7e4fbde483fac5db843263e4a80c76aec2 100644 GIT binary patch delta 672 zcmZXRO-=$q5QX2!XvDa{8?bO`fCW(@CMJp+He$pOb~+*g$uJOp{M*b0TpJTF;F3hQ z-oU$f1M%zTKhC79tGZsjdR_he;=H~&gK{MFm!!C);V{N>@T6GGZr1oqY4(zey2Kvo z951hePKoo_V|?>{xj(;>qbnOp-gw_1@2*_3i{H1Ski(*S>ZqYWHRu}hRfRgxtyi{d_be~6Xt+-Ng4rd zgfxH!mY|5=)HMWIO6uf#AhJsG-;;ad?{ku%qJ#7#Jd=tf40~FmQNc3T$OJI?)5a!3 zY6x)FD1n#@`5(3fOUDWtT_=UijCSnB(uz(e5LS8B zMW`V(;BBn&%&?_RN*wzvJ&PaRW?qt%1Lwf!(RwoA*+Uu*7sLfw^ITn~;cYC8Ji0n? JKgyBMlRuG=Wn};W delta 14 WcmbO+o3Upa 0.008856 ) then + X := Power(X, 1.0/3.0) + else + X := ( 7.787 * X ) + ( 16.0 / 116.0 ); + if ( Y > 0.008856 ) then + Y := Power(Y, 1.0/3.0) + else + Y := ( 7.787 * Y ) + ( 16.0 / 116.0 ); + if ( Z > 0.008856 ) then + Z := Power(Z, 1.0/3.0) + else + Z := ( 7.787 * Z ) + ( 16.0 / 116.0 ); + + L := (116.0 * Y ) - 16.0; + a := 500.0 * ( X - Y ); + b := 200.0 * ( Y - Z ); +end; + +procedure CIELabtoXYZ(L, a, b: Extended; out X, Y, Z: Extended); +begin + Y := ( L + 16 ) / 116.0; + X := ( a / 500.0 )+ Y; + Z := Y - ( b / 200.0 ); + + if ( Power(Y, 3) > 0.008856 ) then + Y := Power(Y, 3) + else + Y := ( Y - (16.0 / 116.0 )) / 7.787; + if ( Power(X, 3) > 0.008856 ) then + X := Power(X, 3) + else + X := ( X - (16.0 / 116.0) ) / 7.787; + if ( Power(Z, 3) > 0.008856 ) then + Z := Power(Z, 3) + else + Z := ( Z - (16.0 / 116.0) ) / 7.787; + + + X := 95.047 * X; + Y := 100.000 * Y; + Z := 108.883 * Z; +end; + end. diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 37e1bc0..3e2b105 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -271,7 +271,7 @@ end; procedure TMFinder.SetToleranceSpeed(nCTS: Integer); begin - if (nCTS < 0) or (nCTS > 2) then + if (nCTS < 0) or (nCTS > 3) then raise Exception.CreateFmt('The given CTS ([%d]) is invalid.',[nCTS]); Self.CTS := nCTS; end; @@ -297,6 +297,7 @@ function TMFinder.SimilarColors(Color1, Color2,Tolerance: Integer) : boolean; var R1,G1,B1,R2,G2,B2 : Byte; H1,S1,L1,H2,S2,L2 : extended; + L_1, a_1, b_1, L_2, a_2 ,b_2, X, Y, Z: extended; begin Result := False; ColorToRGB(Color1,R1,G1,B1); @@ -312,13 +313,30 @@ begin RGBToHSL(R2,g2,b2,H2,S2,L2); Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance)); end; + 3: + begin + RGBToXYZ(R1, G1, B1, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_1, a_1, b_1); + RGBToXYZ(R2, G2, B2, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); + Result := (abs(L_1 - L_2) < Tolerance) + and (abs(a_1 - a_2) < Tolerance) + and (abs(b_1 - b_2) < Tolerance); + end; end; end; +{ + XXX: We should really rewrite this. Once we're adding more colour space we'll + only be adding more and more parameters. It's really silly to push all those + args if we aren't going to use them. We need to make sure the function is + actually inlined. Because if it's not, we should go for a different design. +} function ColorSame(var CTS,Tolerance : Integer; var R1,G1,B1,R2,G2,B2 : byte; var H1,S1,L1,huemod,satmod : extended) : boolean; inline; var H2,S2,L2 : extended; + L_1, a_1, b_1, L_2, a_2 ,b_2, X, Y, Z: extended; begin Result := False; case CTS of @@ -328,6 +346,15 @@ begin RGBToHSL(R2,g2,b2,H2,S2,L2); Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance)); end; + 3: begin + RGBToXYZ(R1, G1, B1, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_1, a_1, b_1); + RGBToXYZ(R2, G2, B2, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); + Result := (abs(L_1 - L_2) < Tolerance) + and (abs(a_1 - a_2) < Tolerance) + and (abs(b_1 - b_2) < Tolerance); + end; end; end; From 52db461f845694d89254c7f0ea5d5fecfc9764f7 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 6 Jun 2011 16:06:17 +0200 Subject: [PATCH 10/37] CTS 3: Now implement the formula properly. --- Units/MMLCore/finder.pas | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 3e2b105..e10ac8a 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -351,9 +351,8 @@ begin XYZtoCIELab(X, Y, Z, L_1, a_1, b_1); RGBToXYZ(R2, G2, B2, X, Y, Z); XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); - Result := (abs(L_1 - L_2) < Tolerance) - and (abs(a_1 - a_2) < Tolerance) - and (abs(b_1 - b_2) < Tolerance); + Result := Sqrt(sqr(L_1 - L_2) + sqr(a_1 - a_2) + + sqr(bb_1 - b_2)) <= Tolerance; end; end; end; From c837d9b96057a58e4cd1a1d5efa241118e1e7d7d Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 16 Jun 2011 16:33:25 +0200 Subject: [PATCH 11/37] CTS 3: Fix typo. --- Units/MMLCore/finder.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index e10ac8a..7b4fb46 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -352,7 +352,7 @@ begin RGBToXYZ(R2, G2, B2, X, Y, Z); XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); Result := Sqrt(sqr(L_1 - L_2) + sqr(a_1 - a_2) + - sqr(bb_1 - b_2)) <= Tolerance; + sqr(b_1 - b_2)) <= Tolerance; end; end; end; From cca7b052135c874064ae9277956a7d078a58dbaf Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 16 Jun 2011 17:03:14 +0200 Subject: [PATCH 12/37] Add CTS 3 to FindColorsTolerance. Conflicts: Units/MMLCore/finder.pas --- Units/MMLCore/finder.pas | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 7b4fb46..3e8d36a 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -1115,7 +1115,7 @@ var for xx := xs to xe do begin if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - begin; + begin ClientTPA[c].x := xx; ClientTPA[c].y := yy; inc(c); @@ -1135,7 +1135,7 @@ var for xx := xs to xe do begin if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then - begin; + begin ClientTPA[c].x := xx; ClientTPA[c].y := yy; inc(c); @@ -1159,7 +1159,32 @@ var begin RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - begin; + begin + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + Inc(c); + end; + Inc(Ptr) + end; + Inc(Ptr, PtrInc); + end; + end; + + procedure cts3; + var xx, yy: integer; + L1, A1, B1, L2, A2, B2, X, Y, Z: extended; + begin + RGBToXYZ(clR, clG, clB, X, Y, Z); + XYZToCieLab(X, Y, Z, L1, A1, B1); + for yy := ys to ye do + begin + for xx := xs to xe do + begin + RGBToXYZ(Ptr^.R, Ptr^.G, Ptr^.B, X, Y, Z); + XYZtoCIELab(X, Y, Z, L2, A2, B2); + if Sqrt(sqr(L1 - L2) + sqr(A1 - A2) + + sqr(B1 - B2)) <= Tol then + begin ClientTPA[c].x := xx; ClientTPA[c].y := yy; Inc(c); @@ -1190,6 +1215,7 @@ begin 0: cts0(); 1: cts1(); 2: cts2(); + 3: cts3(); end; SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); From f19fd6bf8d3589c196d063e1ff4962994606af55 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sun, 3 Jul 2011 20:42:14 +0200 Subject: [PATCH 13/37] Simba/Doc: Add Raymond to doc. --- Doc/sphinx/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/sphinx/conf.py b/Doc/sphinx/conf.py index d7dfee6..14cf164 100644 --- a/Doc/sphinx/conf.py +++ b/Doc/sphinx/conf.py @@ -41,7 +41,7 @@ master_doc = 'index' # General information about the project. project = u'Simba' -copyright = u'2010, Merlijn Wajer' +copyright = u'2010, Merlijn Wajer, Raymond van Venetie' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -176,7 +176,7 @@ htmlhelp_basename = 'Simbadoc' # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'Simba.tex', u'Simba Documentation', - u'Merlijn Wajer', 'manual'), + u'Merlijn Wajer, Raymond van Venetie', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of From a63039914878e2eb40ff21a9c76f757b6e785716 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 13:01:22 +0200 Subject: [PATCH 14/37] Small TODO update. --- TODO | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TODO b/TODO index ba1abf6..9451910 100644 --- a/TODO +++ b/TODO @@ -7,13 +7,16 @@ Simple stuff, not required, may not be possible/useful: - CTS/finder speedups and changes [ ] - General ideas: + - Table displaying all the different performance gains and + penalties. [ ] + - General ideas: - everything subprocedure (lots of code) - jit + comparison function (per cts) generated, call in loop - comparison function (per cts), not generated, call in loop + - Investigate SIMD probable speedups [ ] - JIT (Generate comparison functions) [ ] - Comparison functions for HSL/XYZ/L*a*b should check for match on each component before calculating the next. From 6f896b56a292098a1aef2ddb138ea65ce96ec6a3 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 18:15:33 +0200 Subject: [PATCH 15/37] Finder: Start CTS rework. --- Units/MMLCore/finder.pas | 321 +++++++++++++++++++-------------------- 1 file changed, 155 insertions(+), 166 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 3e8d36a..001bf91 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -107,6 +107,17 @@ uses tpa, //TPABounds dtmutil; + +type + TCTS2Info = record + H, S, L: extended; + hueMod, satMod: extended; + end; + PCTS2Info = ^TCTS2Info; + + TCTSCompareFunction = function (Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; + + procedure TMFinder.LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer); var i,c,Ring : integer; @@ -328,10 +339,7 @@ end; { - XXX: We should really rewrite this. Once we're adding more colour space we'll - only be adding more and more parameters. It's really silly to push all those - args if we aren't going to use them. We need to make sure the function is - actually inlined. Because if it's not, we should go for a different design. + TODO: Remove this } function ColorSame(var CTS,Tolerance : Integer; var R1,G1,B1,R2,G2,B2 : byte; var H1,S1,L1,huemod,satmod : extended) : boolean; inline; var @@ -357,34 +365,92 @@ begin end; end; -{ - TODO: See if this is actually inlined. If it is, we can shorten the - subprocedures; if it is not, either: - - Paste a lot of code. - - Pass a record of the required data to prevent pushing arguments on the - stack. -} -{ Not using var for each arg now, as it should be inlined } -function ColorSame_cts0(Tolerance : Integer; R1,G1,B1,R2,G2,B2 : byte) : boolean; inline; +{ Colour Same functions } +function ColorSame_cts0(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; +var + C1: TRGB32; begin - Result := ((Abs(R1-R2) <= Tolerance) and (Abs(G1-G2) <= Tolerance) and (Abs(B1-B2) <= Tolerance)); + C1 := PRGB32(ctsInfo)^; + Result := (Abs(C1.B - C2^.B) <= Tolerance) + and (Abs(C1.G - C2^.G) <= Tolerance) + and (Abs(C1.R - C2^.R) <= Tolerance); end; -{ Not using var for each arg now, as it should be inlined } -function ColorSame_cts1(Tolerance : Integer; R1,G1,B1,R2,G2,B2 : byte) : boolean; inline; +function ColorSame_cts1(ToleranceSqr: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; +var + C1: TRGB32; + r,g,b: integer; begin - Result := (Sqrt(sqr(R1-R2) + sqr(G1-G2) + sqr(B1-B2)) <= Tolerance); + C1 := PRGB32(ctsInfo)^; + b := C1.B - C2^.B; + b := b * b; + g := C1.G - C2^.G; + g := g * g; + r := C1.R - C2^.R; + r := r * r; + Result := (b + g + r) < ToleranceSqr; end; -function ColorSame_cts2(Tolerance: Integer; H1, S1, L1, H2,S2,L2, hueMod, satMod: extended): - boolean; inline; +function ColorSame_cts2(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; + +var + h, s, l: extended; + i: TCTS2Info; begin - result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and - (abs(S1 - S2) <= (satMod * Tolerance)) - and (abs(L1 - L2) <= Tolerance)); + i := PCTS2Info(ctsInfo)^; + RGBToHSL(C2^.R, C2^.G, C2^.B, h, s, l); // Inline this later. + + Result := (abs(h - i.H) <= (i.hueMod * Tolerance)) + and (abs(s - i.S) <= (i.satMod * Tolerance)) + and (abs(l - i.L) <= Tolerance); +end; + +{ } + +function Create_CTSInfo(cts: integer; Color, Tol: Integer; + hueMod, satMod: extended): Pointer; +var + R, G, B: Integer; + H, S, L: Integer; +begin + case cts of + 0, 1: + begin + Result := AllocMem(SizeOf(TRGB32)); + ColorToRGB(Color, PRGB32(Result)^.R, PRGB32(Result)^.G, + PRGB32(Result)^.B); + end; + 2: + begin + Result := AllocMem(SizeOf(TRGB32)); + ColorToRGB(Color, R, G, B); + RGBToHSL(R, G, B, PCTS2Info(Result)^.H, PCTS2Info(Result)^.S, + PCTS2Info(Result)^.L); + PCTS2Info(Result)^.hueMod := Tol * hueMod; + PCTS2Info(Result)^.satMod := Tol * satMod; + end; + end; +end; + +procedure Free_CTSInfo(i: Pointer); +begin + if assigned(i) then + FreeMem(i) + else + raise Exception.Create('Free_CTSInfo: Invalid TCTSInfo passed'); +end; + +function Get_CTSCompare(cts: Integer): TCTSCompareFunction; + +begin + case cts of + 0: Result := @ColorSame_cts0; + 1: Result := @ColorSame_cts1; + 2: Result := @ColorSame_cts2; + end; end; procedure TMFinder.UpdateCachedValues(NewWidth, NewHeight: integer); @@ -1107,25 +1173,9 @@ var PtrInc,C: Integer; dX, dY, clR, clG, clB: Integer; - procedure cts0; - var xx, yy: integer; - begin - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - begin - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - end; - + xx, yy: integer; + compare: TCTSCompareFunction; + ctsinfo: Pointer; procedure cts1; var xx, yy: integer; @@ -1170,9 +1220,7 @@ var end; end; - procedure cts3; - var xx, yy: integer; - L1, A1, B1, L2, A2, B2, X, Y, Z: extended; + { procedure cts3; begin RGBToXYZ(clR, clG, clB, X, Y, Z); XYZToCieLab(X, Y, Z, L1, A1, B1); @@ -1193,7 +1241,7 @@ var end; Inc(Ptr, PtrInc); end; - end; + end; } begin Result := false; @@ -1201,8 +1249,6 @@ begin dX := xe - xs; dY := ye - ys; - //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -1211,16 +1257,30 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; c := 0; - case CTS of - 0: cts0(); - 1: cts1(); - 2: cts2(); - 3: cts3(); + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if compare(Tol, ctsinfo, Ptr) then + begin + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + inc(c); + end; + inc(Ptr); + end; + Inc(Ptr, PtrInc); end; + SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; TClient(Client).IOManager.FreeReturnData; + Free_CTSInfo(ctsinfo) end; function TMFinder.FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, @@ -1641,111 +1701,28 @@ begin TClient(Client).IOManager.FreeReturnData; end; + +{ + TODO: Implement HSLRows? +} function TMFinder.FindBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean; var - MainRowdata : TPRGB32Array; - PtrData : TRetData; - BmpW,BmpH : integer; - dX, dY: Integer; - SkipCoords : T2DBoolArray; - foundP: TPoint; - - function cts0: tpoint; - var xx, yy, xBmp, yBmp, tmpY: integer; - BmpRowData : TPRGB32Array; - label NotFoundBmp; - begin - BmpRowData:= CalculateRowPtrs(bitmap); - - for yy := 0 to dY do - for xx := 0 to dX do - begin - for yBmp:= 0 to BmpH do - begin - tmpY := yBmp + yy; - for xBmp := 0 to BmpW do - if not SkipCoords[yBmp][xBmp] then - if not ColorSame_cts0(Tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + xx].R, - MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B) then - goto NotFoundBmp; - end; - exit(Point(xx + xs, yy + ys)); - NotFoundBmp: // double break - end; - - Result := Point(-1, -1); - end; + MainRowdata : TPRGB32Array; + BmpRowData : TPRGB32Array; + PtrData : TRetData; + BmpW,BmpH : integer; + xBmp,yBmp : integer; + tmpY : integer; + dX, dY, xx, yy: Integer; + CCTS : integer; + H,S,L,HMod,SMod : extended; + SkipCoords : T2DBoolArray; +label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } - function cts1: tpoint; - var xx, yy, xBmp, yBmp, tmpY: integer; - BmpRowData : TPRGB32Array; - label NotFoundBmp; - begin - BmpRowData:= CalculateRowPtrs(bitmap); - - for yy := 0 to dY do - for xx := 0 to dX do - begin - for yBmp:= 0 to BmpH do - begin - tmpY := yBmp + yy; - for xBmp := 0 to BmpW do - if not SkipCoords[yBmp][xBmp] then - if not ColorSame_cts1(Tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + xx].R, - MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B) then - goto NotFoundBmp; - end; - exit(Point(xx + xs, yy + ys)); - NotFoundBmp: // double break - end; - - Result := Point(-1, -1); - end; - - function cts2: tpoint; - var H2, S2, L2, HMod, SMod: extended; - xx, yy, xBmp, yBmp, tmpY: integer; - - HSLRows: T2DHSLArray; - - label NotFoundBmp; - begin - HSLRows := bitmap.GetHSLValues(0, 0, BmpW, BmpH); - - for yy := 0 to dY do - for xx := 0 to dX do - begin - for yBmp:= 0 to BmpH do - begin - tmpY := yBmp + yy; - for xBmp := 0 to BmpW do - if not SkipCoords[yBmp][xBmp] then - begin - RGBToHSL(MainRowdata[tmpY][xBmp + xx].R, MainRowdata[tmpY][xBmp + xx].G, - MainRowdata[tmpY][xBmp + xx].B, H2, S2, L2); - - if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, - HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, - //if not ColorSame_cts2(Tolerance, HSLRows[yBmp][xBmp].H, HSLRows[yBmp][xBmp].S, HSLRows[yBmp][xBmp].L, - H2, S2, L2, hueMod, satMod) then - goto NotFoundBmp; - end; - end; - exit(Point(xx + xs, yy + ys)); - NotFoundBmp: // double break - end; - - Result := Point(-1, -1); - end; - begin - Result := False; + Result := false; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) DefaultOperations(xs,ys,xe,ye); @@ -1756,31 +1733,43 @@ begin PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); //Caculate the row ptrs MainRowdata:= CalculateRowPtrs(PtrData,dy+1); - - + BmpRowData:= CalculateRowPtrs(bitmap); //Get the 'fixed' bmp size BmpW := bitmap.Width - 1; BmpH := bitmap.Height - 1; //Heck our bitmap cannot be outside the search area dX := dX - bmpW; dY := dY - bmpH; + //Compiler hints + HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; + + CCTS := Self.CTS; //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); + for yy := 0 to dY do + for xx := 0 to dX do + begin; + for yBmp:= 0 to BmpH do + begin; + tmpY := yBmp + yy; + for xBmp := 0 to BmpW do + if not SkipCoords[yBmp][xBmp] then + if not ColorSame(CCTS,tolerance, + BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, + MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, + H,S,L,HMod,SMod) then + goto NotFoundBmp; - case Self.CTS of - 0: foundP := cts0(); - 1: foundP := cts1(); - 2: foundP := cts2(); - end; - - if (foundP.x = -1) and (foundP.y = -1) then - result := False - else begin - x := foundP.x; - y := foundP.y; - Result := True; - end; + end; + //We did find the Bmp, otherwise we would be at the part below + TClient(Client).IOManager.FreeReturnData; + x := xx + xs; + y := yy + ys; + result := true; + exit; + NotFoundBmp: + end; TClient(Client).IOManager.FreeReturnData; end; From e6b005b61f0a4c223d0e8c1f109d28aa48c0ad17 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 18:34:49 +0200 Subject: [PATCH 16/37] Finder: CTS-rework fixes. --- Units/MMLCore/finder.pas | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 001bf91..4dd4f48 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -391,7 +391,7 @@ begin g := g * g; r := C1.R - C2^.R; r := r * r; - Result := (b + g + r) < ToleranceSqr; + Result := (b + g + r) <= ToleranceSqr; end; function ColorSame_cts2(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; @@ -425,7 +425,7 @@ begin end; 2: begin - Result := AllocMem(SizeOf(TRGB32)); + Result := AllocMem(SizeOf(TCTS2Info)); ColorToRGB(Color, R, G, B); RGBToHSL(R, G, B, PCTS2Info(Result)^.H, PCTS2Info(Result)^.S, PCTS2Info(Result)^.L); @@ -1279,8 +1279,8 @@ begin SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; - Free_CTSInfo(ctsinfo) end; function TMFinder.FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, From 733a8cbf320ca29f1edf60b9e29f1ae5c0d68b67 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 20:39:44 +0200 Subject: [PATCH 17/37] Finder: More fixes. :-) --- Units/MMLCore/finder.pas | 56 +++++----------------------------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 4dd4f48..bcbdaf3 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -386,12 +386,9 @@ var begin C1 := PRGB32(ctsInfo)^; b := C1.B - C2^.B; - b := b * b; g := C1.G - C2^.G; - g := g * g; r := C1.R - C2^.R; - r := r * r; - Result := (b + g + r) <= ToleranceSqr; + Result := (b*b + g*g + r*r) <= ToleranceSqr; end; function ColorSame_cts2(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; @@ -403,8 +400,8 @@ begin i := PCTS2Info(ctsInfo)^; RGBToHSL(C2^.R, C2^.G, C2^.B, h, s, l); // Inline this later. - Result := (abs(h - i.H) <= (i.hueMod * Tolerance)) - and (abs(s - i.S) <= (i.satMod * Tolerance)) + Result := (abs(h - i.H) <= (i.hueMod)) + and (abs(s - i.S) <= (i.satMod)) and (abs(l - i.L) <= Tolerance); end; @@ -838,7 +835,6 @@ begin Ptr := Before; Break; end; - Inc(Ptr, PtrInc); end; end; Inc(Ptr); @@ -1177,49 +1173,6 @@ var compare: TCTSCompareFunction; ctsinfo: Pointer; - procedure cts1; - var xx, yy: integer; - begin - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then - begin - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - end; - - procedure cts2; - var xx, yy: integer; - H1, S1, L1, H2, S2, L2, hueXTol, satXTol: Extended; - begin - ColorToHSL(color,H1,S1,L1); - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - begin - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - Inc(c); - end; - Inc(Ptr) - end; - Inc(Ptr, PtrInc); - end; - end; - { procedure cts3; begin RGBToXYZ(clR, clG, clB, X, Y, Z); @@ -1261,6 +1214,9 @@ begin ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); compare := Get_CTSCompare(Self.CTS); + if cts = 1 then + tol := tol * tol; + for yy := ys to ye do begin for xx := xs to xe do From cda571dcb0a3f3f755a63978d07f2a25f83861a7 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 21:06:17 +0200 Subject: [PATCH 18/37] Finder: Remote tolerance param. Cleanups. --- Units/MMLCore/finder.pas | 157 ++++++++++++++++----------------------- 1 file changed, 63 insertions(+), 94 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index bcbdaf3..b9473e7 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -109,13 +109,26 @@ uses type + TCTS0Info = record + B, G, R, A: byte; + Tol: Integer; + end; + PCTS0Info = ^TCTS0Info; + + TCTS1Info = record + B, G, R, A: byte; + Tol: Integer; { Squared } + end; + PCTS1Info = ^TCTS1Info; + TCTS2Info = record H, S, L: extended; hueMod, satMod: extended; + Tol: Integer; end; PCTS2Info = ^TCTS2Info; - TCTSCompareFunction = function (Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; + TCTSCompareFunction = function (ctsInfo: Pointer; C2: PRGB32): boolean; procedure TMFinder.LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer); @@ -367,31 +380,31 @@ end; { Colour Same functions } -function ColorSame_cts0(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; +function ColorSame_cts0(ctsInfo: Pointer; C2: PRGB32): boolean; var - C1: TRGB32; + C1: TCTS0Info; begin - C1 := PRGB32(ctsInfo)^; - Result := (Abs(C1.B - C2^.B) <= Tolerance) - and (Abs(C1.G - C2^.G) <= Tolerance) - and (Abs(C1.R - C2^.R) <= Tolerance); + C1 := PCTS0Info(ctsInfo)^; + Result := (Abs(C1.B - C2^.B) <= C1.Tol) + and (Abs(C1.G - C2^.G) <= C1.Tol) + and (Abs(C1.R - C2^.R) <= C1.Tol); end; -function ColorSame_cts1(ToleranceSqr: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; +function ColorSame_cts1(ctsInfo: Pointer; C2: PRGB32): boolean; var - C1: TRGB32; + C1: TCTS1Info; r,g,b: integer; begin - C1 := PRGB32(ctsInfo)^; + C1 := PCTS1Info(ctsInfo)^; b := C1.B - C2^.B; g := C1.G - C2^.G; r := C1.R - C2^.R; - Result := (b*b + g*g + r*r) <= ToleranceSqr; + Result := (b*b + g*g + r*r) <= C1.Tol; end; -function ColorSame_cts2(Tolerance: Integer; ctsInfo: Pointer; C2: PRGB32): boolean; +function ColorSame_cts2(ctsInfo: Pointer; C2: PRGB32): boolean; var h, s, l: extended; @@ -402,7 +415,7 @@ begin Result := (abs(h - i.H) <= (i.hueMod)) and (abs(s - i.S) <= (i.satMod)) - and (abs(l - i.L) <= Tolerance); + and (abs(l - i.L) <= i.Tol); end; { } @@ -414,11 +427,19 @@ var H, S, L: Integer; begin case cts of - 0, 1: + 0: begin - Result := AllocMem(SizeOf(TRGB32)); - ColorToRGB(Color, PRGB32(Result)^.R, PRGB32(Result)^.G, - PRGB32(Result)^.B); + Result := AllocMem(SizeOf(TCTS0Info)); + ColorToRGB(Color, PCTS0Info(Result)^.R, PCTS0Info(Result)^.G, + PCTS0Info(Result)^.B); + PCTS0Info(Result)^.Tol := Tol; + end; + 1: + begin + Result := AllocMem(SizeOf(TCTS1Info)); + ColorToRGB(Color, PCTS1Info(Result)^.R, PCTS1Info(Result)^.G, + PCTS1Info(Result)^.B); + PCTS1Info(Result)^.Tol := Tol*Tol; end; 2: begin @@ -984,67 +1005,11 @@ var Ptr: PRGB32; PtrInc: Integer; dX, dY, clR, clG, clB: Integer; - xy: TPoint; + xx, yy: integer; + compare: TCTSCompareFunction; + ctsinfo: Pointer; + label Hit; - function cts0: tpoint; - var xx, yy: integer; - begin - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and - (Abs(clR-Ptr^.R) <= Tol)) then - exit(Point(xx, yy)); - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - - Result := Point(-1, -1); - end; - - function cts1: tpoint; - var xx, yy: integer; - begin - Tol := Sqr(Tol); - - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then - exit(Point(xx, yy)); - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - - Result := Point(-1, -1); - end; - - function cts2: tpoint; - var xx, yy: integer; - H1, S1, L1, H2, S2, L2: Extended; - HueXTol, SatXTol: Extended; - begin - RGBToHSL(clR,clG,clB,H1,S1,L1); - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - exit(Point(xx, yy)); - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - - Result := Point(-1, -1); - end; begin Result := false; @@ -1054,8 +1019,6 @@ begin // calculate delta x and y dX := xe - xs; dY := ye - ys; - //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -1064,23 +1027,29 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; - case CTS of - 0: xy := cts0(); - 1: xy := cts1(); - 2: xy := cts2(); + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + + for yy := ys to ye do + begin + for xx := xs to xe do + begin + if compare(ctsinfo, Ptr) then + goto Hit; + inc(Ptr); + end; + Inc(Ptr, PtrInc); end; - if (xy.x = -1) and (xy.y = -1) then - begin - Result := False; - TClient(Client).IOManager.FreeReturnData; - Exit; - end else - begin + + Result := False; + TClient(Client).IOManager.FreeReturnData; + Exit; + + Hit: Result := True; - x := xy.x; - y := xy.y; + x := xx; + y := yy; TClient(Client).IOManager.FreeReturnData; - end; end; function TMFinder.FindColoredAreaTolerance(var x, y: Integer; Color, xs, ys, xe, ye, MinArea, tol: Integer): Boolean; @@ -1221,7 +1190,7 @@ begin begin for xx := xs to xe do begin - if compare(Tol, ctsinfo, Ptr) then + if compare(ctsinfo, Ptr) then begin ClientTPA[c].x := xx; ClientTPA[c].y := yy; From 79021409d05c24da797f73299744e588effd381c Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Wed, 6 Jul 2011 21:34:03 +0200 Subject: [PATCH 19/37] Finder: CTS 2 fix. --- Units/MMLCore/finder.pas | 1 + 1 file changed, 1 insertion(+) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index b9473e7..de989b9 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -449,6 +449,7 @@ begin PCTS2Info(Result)^.L); PCTS2Info(Result)^.hueMod := Tol * hueMod; PCTS2Info(Result)^.satMod := Tol * satMod; + PCTS2Info(Result)^.Tol := Tol; end; end; end; From f5c9690bee157f9e8dc82a7d23c5841629e8599c Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 7 Jul 2011 11:59:15 +0200 Subject: [PATCH 20/37] Finder: More rework and cleanups. --- Units/MMLCore/finder.pas | 80 +++++++++++----------------------------- 1 file changed, 22 insertions(+), 58 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index de989b9..99a916d 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -69,7 +69,7 @@ type function FindColorSpiralTolerance(var x, y: Integer; color, xs, ys, xe, ye,Tol: Integer): Boolean; function FindColorTolerance(out x, y: Integer; Color, xs, ys, xe, ye, tol: Integer): Boolean; function FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; - function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer) : boolean; + function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tol: Integer) : boolean; function FindColors(var TPA: TPointArray; Color, xs, ys, xe, ye: Integer): Boolean; function FindColoredArea(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea: Integer): Boolean; function FindColoredAreaTolerance(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea, tol: Integer): Boolean; @@ -1205,6 +1205,7 @@ begin SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -1340,63 +1341,17 @@ begin end; function TMFinder.FindColorsSpiralTolerance(x, y: Integer; - out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer + out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tol: Integer ): boolean; var PtrData: TRetData; c : integer; RowData : TPRGB32Array; - dX, dY, clR, clG, clB, SpiralHi: Integer; + dX, dY, SpiralHi, i: Integer; - procedure cts0; - var i: integer; - begin - for i := 0 to SpiralHi do - if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tolerance) and - (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tolerance) and - (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - end; + compare: TCTSCompareFunction; + ctsinfo: Pointer; - procedure cts1; - var i: integer; - begin - for i := 0 to SpiralHi do - if (Sqrt(sqr(clR - RowData[ClientTPA[i].y][ClientTPA[i].x].R) + - sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + - sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B)) <= Tolerance) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - end; - - procedure cts2; - var i: integer; - H1, S1, L1, H2, S2, L2, HueXTol, SatXTol: Extended; - begin - ColorToHSL(Color, H1, S1, L1); - HueXTol := hueMod * Tolerance; - SatXTol := satMod * Tolerance; - for i := 0 to SpiralHi do - begin; - RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, - RowData[ClientTPA[i].y][ClientTPA[i].x].G, - RowData[ClientTPA[i].y][ClientTPA[i].x].B, - H2,S2,L2); - if ((abs(H1 - H2) <= (HueXTol)) and (abs(S1 - S2) <= (satXTol)) and (abs(L1 - L2) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - end; - end; begin Result := false; DefaultOperations(xs,ys,xe,ye); @@ -1404,25 +1359,34 @@ begin dX := xe - xs; dY := ye - ys; //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); c := 0; + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + //Load rowdata RowData:= CalculateRowPtrs(ptrdata,dy+1); //Load the spiral path - LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); + LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); { Fills ClientTPA with Spiral path } + SpiralHi := (dx + 1) * (dy + 1) - 1; - case CTS of - 0: cts0(); - 1: cts1(); - 2: cts2(); - end; + for i := 0 to SpiralHi do + if compare(ctsinfo, @RowData[ClientTPA[i].y][ClientTPA[i].x]) then + begin; + { We can re-use the ClientTPA to store results. } + ClientTPA[c].x := ClientTPA[i].x + xs; + ClientTPA[c].y := ClientTPA[i].y + ys; + inc(c); + end; + SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; + + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; From 031654b3d1120de61fc3a5b7923656f6d0108e2d Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sun, 17 Jul 2011 19:36:21 +0200 Subject: [PATCH 21/37] Documentation: Initial libMML documentation. --- Doc/sphinx/index.rst | 1 + Doc/sphinx/libmml.rst | 11 +++++++ Doc/sphinx/libmml/intro.rst | 61 +++++++++++++++++++++++++++++++++++++ Doc/sphinx/pymml.rst | 1 - 4 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 Doc/sphinx/libmml.rst create mode 100644 Doc/sphinx/libmml/intro.rst diff --git a/Doc/sphinx/index.rst b/Doc/sphinx/index.rst index aec03f4..28e48ef 100644 --- a/Doc/sphinx/index.rst +++ b/Doc/sphinx/index.rst @@ -31,6 +31,7 @@ Contents: referencesimba.rst docdoc.rst todo.rst + libmml.rst pymml.rst diff --git a/Doc/sphinx/libmml.rst b/Doc/sphinx/libmml.rst new file mode 100644 index 0000000..607a244 --- /dev/null +++ b/Doc/sphinx/libmml.rst @@ -0,0 +1,11 @@ + +.. _lib-mml: + +libMML +========== + +.. toctree:: + :maxdepth: 2 + + libmml/intro.rst + diff --git a/Doc/sphinx/libmml/intro.rst b/Doc/sphinx/libmml/intro.rst new file mode 100644 index 0000000..fdd6020 --- /dev/null +++ b/Doc/sphinx/libmml/intro.rst @@ -0,0 +1,61 @@ +libMML +====== + +libMML is short for the library to the Mufasa Macro Library. + + +Why libMML? +----------- + +One of the first questions that rise are probably *why* libMML and *what* is +libMML exactly? + +libMML is a loadable C-like library that provides most of the MML functionality. +For the ones that do not know, MML is the core component for Simba that does all +the *computational* and *algorithmic* work. See :ref:`mml-ref` for more +information. + +To summarize, the MML covers: + + - Targetting specific windows and getting the window information such as + their bitmaps and dimensions. + - Controlling the mouse and keyboard. + - Finding colours, bitmaps and dtms. + - Text recognition (OCR) + - Accessing files and sockets in an unified manner + +Hopefully the *what* part of the question has mainly been covered by now. If +you're literate in computer science the *why* question has also been answered as +soon as it was mentioned that is was a loadable library - which is also implied +by its name. Exporting the MML into a loadable library allows virtually any +program to load it and just use all the MML functionality. + +Design (issues) +--------------- + +libMML itself should not be too complex. It should simply translate the OOP MML +to a non-OOP C-type library and convert datatypes when required (see below as to +why). libMML is basically just a codebase that calls MML functions and passes +the result along in a slightly different format. In simple cases such as +MoveMouse the integers are simply passed; since there's do not differ, but in +the case of arrays of any type we have to copy the arrays to a C format - at +least until MML internally will no longer use Free Pascal (managed) arrays. + +As previously mentioned, libMML is a *C*-type library; this is mentioned +explicitly because MML is written in Free Pascal (Object Pascal) which has quite +a few different datatypes. Strings are typically not compatible, and arrays are +managed in Pascal whereas they are not in C which makes it hard to just *pass* +the array along. One of the problems we have to cope with when writing libMML is +converting datatypes to C-compatible datatypes. C-compatible datatypes are +supported by most programming languages and thus the best way to go when making +a universal MML library. + +libMML use cases +---------------- + +Theoretically libMML can be loaded by any programming language; but typically +each programming languages has it's own kind of programming practices and thus +write - again - their own wrapper around libMML. This is what is being done with +*pyMML*, the python libMML wrapper. It is still as much in development as libMML +is, but the functionality exposed by libMML is succesfully used. + diff --git a/Doc/sphinx/pymml.rst b/Doc/sphinx/pymml.rst index 664ee22..63838f9 100644 --- a/Doc/sphinx/pymml.rst +++ b/Doc/sphinx/pymml.rst @@ -6,7 +6,6 @@ Python MML .. toctree:: :maxdepth: 2 - pymml/mml.rst pymml/mouse.rst pymml/color.rst From 8abd502580fa782541095cdcb04cb3ba99f304cd Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sun, 17 Jul 2011 19:37:33 +0200 Subject: [PATCH 22/37] Documentation: Bump version to 820. --- Doc/sphinx/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/sphinx/conf.py b/Doc/sphinx/conf.py index 14cf164..0f7dba2 100644 --- a/Doc/sphinx/conf.py +++ b/Doc/sphinx/conf.py @@ -48,9 +48,9 @@ copyright = u'2010, Merlijn Wajer, Raymond van Venetie' # built documents. # # The short X.Y version. -version = '0.810' +version = '0.820' # The full version, including alpha/beta/rc tags. -release = '0.810' +release = '0.820' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 153025f08035a1125010bd6b7bf62dca57f084a0 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sun, 17 Jul 2011 19:51:16 +0200 Subject: [PATCH 23/37] libMML: Changed the indentation. --- Projects/libmml/libmml.lpr | 709 +++++++++++++++++++------------------ 1 file changed, 356 insertions(+), 353 deletions(-) diff --git a/Projects/libmml/libmml.lpr b/Projects/libmml/libmml.lpr index 4260876..152b06c 100644 --- a/Projects/libmml/libmml.lpr +++ b/Projects/libmml/libmml.lpr @@ -15,6 +15,11 @@ Const MOUSE_UP = 0; MOUSE_DOWN = 1; +{ + Global variables. + To actually read the last_error, make sure you copy it to a safe place + directly after the function call. +} var last_error: String; debug: boolean; @@ -23,28 +28,28 @@ var function init: integer; cdecl; begin - last_error := ''; - debug := true; - result := RESULT_OK; + last_error := ''; + debug := true; + result := RESULT_OK; end; procedure set_last_error(s: string); begin - last_error := s; - if debug then - writeln('ERROR: ' + s); + last_error := s; + if debug then + writeln('ERROR: ' + s); end; { Validate the TClient. If it is NULL, set last error and return false } function validate_client(C: TClient): boolean; inline; begin - result := Assigned(C); - if not result then - begin - last_error := 'PClient is NULL'; - if debug then - writeln(last_error); - end; + result := Assigned(C); + if not result then + begin + last_error := 'PClient is NULL'; + if debug then + writeln(last_error); + end; end; { @@ -55,42 +60,42 @@ function create_client: PtrUInt; cdecl; var C: TClient; begin - try - C := TClient.Create(''); - Result := PtrUInt(C); - except on e : Exception do - begin - // FIXME UINT negative - result := PtrUInt(RESULT_ERROR); - set_last_error(e.message); - end; - end; - writeln(format('C: %d, IOManager: %d', [PtrUInt(C), PtrUInt(C.IOManager)])); + try + C := TClient.Create(''); + Result := PtrUInt(C); + except on e : Exception do + begin + // FIXME UINT negative + result := PtrUInt(RESULT_ERROR); + set_last_error(e.message); + end; + end; + writeln(format('C: %d, IOManager: %d', [PtrUInt(C), PtrUInt(C.IOManager)])); end; { Destroy a TClient } function destroy_client(C: TClient): integer; cdecl; begin - try - C.Free; - except on e : Exception do - begin - result := RESULT_ERROR; - set_last_error(e.message); - end; - end; + try + C.Free; + except on e : Exception do + begin + result := RESULT_ERROR; + set_last_error(e.message); + end; + end; end; { Set (verbose) debug on/off } procedure set_debug(v: Boolean); cdecl; begin - debug := v; + debug := v; end; { Get debug } function get_debug: boolean; cdecl; begin - exit(debug); + exit(debug); end; { @@ -101,40 +106,40 @@ end; } function get_last_error: pchar; cdecl; begin - exit(@last_error[1]); + exit(@last_error[1]); end; { Turn an array into a pointer. The pointer memory is not managed by FPC, so we can pass it along happily. It'll have to be freed by the external control though } function array_to_ptr(ptr: Pointer; size: PtrUInt; objsize: PtrUInt): Pointer; cdecl; begin - result := GetMem(objsize * size); - Move(ptr^, result^, objsize * size); + result := GetMem(objsize * size); + Move(ptr^, result^, objsize * size); end; { Free memory previously allocated by libMML } function free_ptr(ptr: pointer): boolean; cdecl; begin - result := Assigned(ptr); - if not result then - begin - set_last_error('TClient is NULL'); - if debug then - writeln(last_error); - end else - FreeMem(ptr); + result := Assigned(ptr); + if not result then + begin + set_last_error('TClient is NULL'); + if debug then + writeln(last_error); + end else + FreeMem(ptr); end; { Allocate memory with libMML } function alloc_mem(size, objsize: PtrUInt): Pointer; cdecl; begin - result := GetMem(size * objsize); + result := GetMem(size * objsize); end; { Reallocate memory with libMML } function realloc_mem(ptr: Pointer; size, objsize: PtrUInt): Pointer; cdecl; begin - result := ReAllocMem(ptr, size*objsize); + result := ReAllocMem(ptr, size*objsize); end; { Mouse } @@ -143,34 +148,32 @@ end; function get_mouse_pos(C: TClient; var t: tpoint): integer; cdecl; begin - if not validate_client(C) then + if not validate_client(C) then + exit(RESULT_ERROR); + + try + C.IOManager.GetMousePos(t.x,t.y); + result := RESULT_OK; + except on e : Exception do begin - exit(RESULT_ERROR); - end; - - try - C.IOManager.GetMousePos(t.x,t.y); - result := RESULT_OK; - except on e : Exception do - begin - result := RESULT_ERROR; - set_last_error(e.Message); - end; + result := RESULT_ERROR; + set_last_error(e.Message); end; + end; end; { Set mouse position of client C to point t } function set_mouse_pos(C: TClient; var t: tpoint): integer; cdecl; begin - try - C.IOManager.MoveMouse(t.x,t.y); - result := RESULT_OK; - except on e : Exception do + try + C.IOManager.MoveMouse(t.x,t.y); + result := RESULT_OK; + except on e : Exception do begin result := RESULT_ERROR; set_last_error(e.Message); end; - end; + end; end; @@ -187,38 +190,38 @@ end; { Return the state of a mouse button given client C } function get_mouse_button_state(C: TClient; But: Integer): Integer; cdecl; begin - try - if C.IOManager.IsMouseButtonDown(ConvIntClickType(But)) then - result := MOUSE_DOWN - else - result := MOUSE_UP; - except on e : Exception do + try + if C.IOManager.IsMouseButtonDown(ConvIntClickType(But)) then + result := MOUSE_DOWN + else + result := MOUSE_UP; + except on e : Exception do begin - result := RESULT_ERROR; - set_last_error(e.Message); - end; + result := RESULT_ERROR; + set_last_error(e.Message); end; + end; end; { Set the state of a mouse button given client C } function set_mouse_button_state(C: TClient; But, State, X, Y: Integer): Integer; cdecl; begin - try - if State = MOUSE_UP then - begin - C.IOManager.ReleaseMouse(X, Y, ConvIntClickType(But)); - result := RESULT_OK; - end else if state = MOUSE_DOWN then - begin - C.IOManager.HoldMouse(X, Y, ConvIntClickType(But)); - result := RESULT_OK; - end; - except on e : Exception do + try + if State = MOUSE_UP then begin - result := RESULT_ERROR; - set_last_error(e.Message); + C.IOManager.ReleaseMouse(X, Y, ConvIntClickType(But)); + result := RESULT_OK; + end else if state = MOUSE_DOWN then + begin + C.IOManager.HoldMouse(X, Y, ConvIntClickType(But)); + result := RESULT_OK; end; + except on e : Exception do + begin + result := RESULT_ERROR; + set_last_error(e.Message); end; + end; end; @@ -227,52 +230,52 @@ end; function get_color(C: TClient; x, y: Integer; out color: Integer): Integer; cdecl; begin - try - color := C.IOManager.GetColor(x, y); - if color > -1 then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + color := C.IOManager.GetColor(x, y); + if color > -1 then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; { Find color on client C in area (x1,y1,x2,y2) and return coordinate (if any) in x, y } function find_color(C: TClient; var x, y: Integer; color, x1, y1, x2, y2: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColor(x, y, color, x1, y1, x2, y2) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColor(x, y, color, x1, y1, x2, y2) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.Message); - result := RESULT_ERROR; - end; + set_last_error(e.Message); + result := RESULT_ERROR; end; + end; end; function find_color_tolerance(C: TClient; var x, y: Integer; color: Integer; tol, x1, y1, x2, y2: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColorTolerance(x, y, color, x1, y1, x2, y2, tol) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColorTolerance(x, y, color, x1, y1, x2, y2, tol) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.Message); - result := RESULT_ERROR; - end; + set_last_error(e.Message); + result := RESULT_ERROR; end; + end; end; function find_color_tolerance_optimised(C: TClient; var x, y: Integer; @@ -280,18 +283,18 @@ function find_color_tolerance_optimised(C: TClient; var x, y: Integer; x1, y1, x2, y2: Integer; tol: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColorToleranceOptimised(x, y, col, x1, y1, x2, y2, - tol) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColorToleranceOptimised(x, y, col, x1, y1, x2, y2, + tol) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function find_colors(C: TClient; var ptr: PPoint; var len: Integer; @@ -299,27 +302,27 @@ function find_colors(C: TClient; var ptr: PPoint; var len: Integer; var TPA: TPointArray; begin - setlength(TPA, 0); - try - C.MFinder.FindColors(TPA, color, x1, y1, x2, y2); - except on e : Exception do + setlength(TPA, 0); + try + C.MFinder.FindColors(TPA, color, x1, y1, x2, y2); + except on e : Exception do begin - set_last_error(e.Message); - result := RESULT_ERROR; + set_last_error(e.Message); + result := RESULT_ERROR; end; - end; - - len := Length(TPA); - if len > 0 then - result := RESULT_OK - else - begin - setlength(tpa, 0); - exit(RESULT_FALSE); - end; - - ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); + end; + + len := Length(TPA); + if len > 0 then + result := RESULT_OK + else + begin setlength(tpa, 0); + exit(RESULT_FALSE); + end; + + ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); + setlength(tpa, 0); end; function find_colors_tolerance(C: TClient; var ptr: PPoint; var len: Integer; @@ -327,26 +330,26 @@ function find_colors_tolerance(C: TClient; var ptr: PPoint; var len: Integer; var TPA: TPointArray; begin - try - C.MFinder.FindColorsTolerance(TPA, color, x1, y1, x2, y2, tol); - except on e : Exception do + try + C.MFinder.FindColorsTolerance(TPA, color, x1, y1, x2, y2, tol); + except on e : Exception do begin - set_last_error(e.Message); - result := RESULT_ERROR; - end; - end; - - len := Length(TPA); - if len > 0 then - result := RESULT_OK - else - begin - setlength(tpa, 0); - exit(RESULT_FALSE); + set_last_error(e.Message); + result := RESULT_ERROR; end; + end; - ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); - setlength(TPA, 0); + len := Length(TPA); + if len > 0 then + result := RESULT_OK + else + begin + setlength(tpa, 0); + exit(RESULT_FALSE); + end; + + ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); + setlength(TPA, 0); end; function find_colors_tolerance_optimised(C: TClient; var ptr: PPoint; @@ -356,184 +359,184 @@ function find_colors_tolerance_optimised(C: TClient; var ptr: PPoint; var TPA: TPointArray; begin - try - C.MFinder.FindColorsToleranceOptimised(TPA, col, x1, y1, x2, y2, tol); - except on e : Exception do + try + C.MFinder.FindColorsToleranceOptimised(TPA, col, x1, y1, x2, y2, tol); + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; + set_last_error(e.message); + result := RESULT_ERROR; end; - end; - - len := Length(TPA); - if len > 0 then - result := RESULT_OK - else - begin - setlength(tpa, 0); - exit(RESULT_FALSE); - end; - - ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); - setlength(TPA, 0); + end; + + len := Length(TPA); + if len > 0 then + result := RESULT_OK + else + begin + setlength(tpa, 0); + exit(RESULT_FALSE); + end; + + ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); + setlength(TPA, 0); end; function similar_colors(C: TClient; col1, col2, tol: Integer): Integer; cdecl; begin - try - if C.MFinder.SimilarColors(col1, col2, tol) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.SimilarColors(col1, col2, tol) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_FALSE; - end; + set_last_error(e.message); + result := RESULT_FALSE; end; + end; end; function count_color(C: TClient; out count: Integer; Color, xs, ys, xe, ye: Integer): Integer; cdecl; begin - try - count := C.MFinder.CountColor(Color, xs, ys, xe, ye); - if count > 0 then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + count := C.MFinder.CountColor(Color, xs, ys, xe, ye); + if count > 0 then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function count_color_tolerance(C: TClient; out count: Integer; col: Integer; xs, ys, xe, ye, tol: Integer): Integer; cdecl; begin - try - count := C.MFinder.CountColorTolerance(col, xs, ys, xe, ye, tol); - except on e : Exception do + try + count := C.MFinder.CountColorTolerance(col, xs, ys, xe, ye, tol); + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; - if count > 0 then - result := RESULT_OK - else - result := RESULT_FALSE; + if count > 0 then + result := RESULT_OK + else + result := RESULT_FALSE; end; function find_color_spiral(C: TClient; var x, y: Integer; col, xs, ys, xe, ye: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColorSpiral(x, y, col, xs, ys, xe, ye) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColorSpiral(x, y, col, xs, ys, xe, ye) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function find_color_spiral_tolerance(C: TClient; var x, y: Integer; col, xs, ys, xe, ye: Integer; tol: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColorSpiralTolerance(x, y, col, xs, ys, xe, ye, - tol) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColorSpiralTolerance(x, y, col, xs, ys, xe, ye, + tol) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function find_colored_area(C: TClient; var x, y: Integer; col, xs, ys, xe, ye, minA: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColoredArea(x, y, col, xs, ys, xe, ye, minA) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColoredArea(x, y, col, xs, ys, xe, ye, minA) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function find_colored_area_tolerance(C: TClient; var x, y: Integer; col, xs, ys, xe, ye, minA: Integer; tol: Integer): Integer; cdecl; begin - try - if C.MFinder.FindColoredAreaTolerance(x, y, col, - xs, ys, xe, ye, minA, tol) then - result := RESULT_OK - else - result := RESULT_FALSE; - except on e : Exception do + try + if C.MFinder.FindColoredAreaTolerance(x, y, col, + xs, ys, xe, ye, minA, tol) then + result := RESULT_OK + else + result := RESULT_FALSE; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function set_tolerance_speed(C: TClient; nCTS: Integer): Integer; cdecl; begin - try - C.MFinder.SetToleranceSpeed(nCTS); - result := RESULT_OK; - except on e : Exception do + try + C.MFinder.SetToleranceSpeed(nCTS); + result := RESULT_OK; + except on e : Exception do begin - set_last_error(e.message); - result := RESULT_ERROR; - end; + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function get_tolerance_speed(C: TClient; out cts: Integer): Integer; cdecl; begin - try - cts := C.MFinder.GetToleranceSpeed; - result := RESULT_OK; - except on e: Exception do - begin; - set_last_error(e.message); - result := RESULT_ERROR; + try + cts := C.MFinder.GetToleranceSpeed; + result := RESULT_OK; + except on e: Exception do + begin + set_last_error(e.message); + result := RESULT_ERROR; end - end; + end; end; function set_tolerance_speed_2_modifiers(C: TClient; nHue, nSat: Extended): Integer; cdecl; begin - try - C.MFinder.SetToleranceSpeed2Modifiers(nHue, nSat); - result := RESULT_OK; - except on e : Exception do - begin; - set_last_error(e.message); - result := RESULT_ERROR; - end; + try + C.MFinder.SetToleranceSpeed2Modifiers(nHue, nSat); + result := RESULT_OK; + except on e : Exception do + begin + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; function get_tolerance_speed_2_modifiers(C: TClient; out hueMod: Extended; @@ -541,17 +544,17 @@ function get_tolerance_speed_2_modifiers(C: TClient; out hueMod: Extended; var h, s: Extended; begin - try - C.MFinder.GetToleranceSpeed2Modifiers(h, s); - hueMod := h; - satMod := s; - result := RESULT_OK; - except on e : Exception do - begin; - set_last_error(e.message); - result := RESULT_ERROR; - end; + try + C.MFinder.GetToleranceSpeed2Modifiers(h, s); + hueMod := h; + satMod := s; + result := RESULT_OK; + except on e : Exception do + begin + set_last_error(e.message); + result := RESULT_ERROR; end; + end; end; { DTM } @@ -564,53 +567,53 @@ function create_dtm(PointLen: integer; Points: PMDTMPoint; DTM: TMDTM): integer; var i: integer; begin - DTM := TMDTM.Create; - for i := 0 to PointLen - 1 do - DTM.AddPoint(Points[i]); - - if DTM.Valid then - exit(RESULT_OK); - - DTM.Free; - set_last_error('Invalid DTM'); - result := RESULT_ERROR; + DTM := TMDTM.Create; + for i := 0 to PointLen - 1 do + DTM.AddPoint(Points[i]); + + if DTM.Valid then + exit(RESULT_OK); + + DTM.Free; + set_last_error('Invalid DTM'); + result := RESULT_ERROR; end; { Delete a MDTM. Don't delete it if it is managed! use remove_dtm instead } function delete_dtm(C: TClient; DTM: TMDTM): integer; cdecl; begin - if not assigned(DTM) then - begin - set_last_error('DTM is NULL'); - exit(RESULT_ERROR); - end; - - DTM.Free; - - result := RESULT_OK; + if not assigned(DTM) then + begin + set_last_error('DTM is NULL'); + exit(RESULT_ERROR); + end; + + DTM.Free; + + result := RESULT_OK; end; { Add a previously created DTM to the DTM Manager } function add_dtm(C: TClient; DTM: TMDTM; var index: integer): integer; cdecl; begin - if not assigned(DTM) then - begin - set_last_error('DTM is NULL'); - exit(RESULT_ERROR); - end; - - try - index := C.MDTMs.AddDTM(DTM); - exit(RESULT_OK); - except on e : Exception do - result := RESULT_ERROR; - end; + if not assigned(DTM) then + begin + set_last_error('DTM is NULL'); + exit(RESULT_ERROR); + end; + + try + index := C.MDTMs.AddDTM(DTM); + exit(RESULT_OK); + except on e : Exception do + result := RESULT_ERROR; + end; end; { Remove a previously added DTM from the DTM manager. This also frees the DTM } function remove_dtm(C: TClient; DTMi: integer): integer; cdecl; begin - C.MDTMs.FreeDTM(DTMi); + C.MDTMs.FreeDTM(DTMi); end; { Find a DTM given DTM index i, client C in area x1,y1,x2,y2. Return coord at x, y. } @@ -619,19 +622,19 @@ function find_dtm(C: TClient; DTMi: integer; var x, y: integer; x1, y1, x2, var res: boolean; begin - try - res := C.MFinder.FindDTM(C.MDTMs.DTM[DTMi], x, y, x1, y1, x2, y2); - except on e : Exception do + try + res := C.MFinder.FindDTM(C.MDTMs.DTM[DTMi], x, y, x1, y1, x2, y2); + except on e : Exception do begin; - result := RESULT_ERROR; - set_last_error(e.Message); + result := RESULT_ERROR; + set_last_error(e.Message); end; - end; - - if res then - result := RESULT_OK - else - result := RESULT_FALSE; + end; + + if res then + result := RESULT_OK + else + result := RESULT_FALSE; end; { Find a DTM given DTM index i, client C in area x1,y1,x2,y2. Return coord at x, y. } @@ -642,46 +645,46 @@ var len: integer; TPA: TPointArray; begin - try - res := C.MFinder.FindDTMs(C.MDTMs.DTM[DTMi], TPA, x1, y1, x2, y2); - except on e : Exception do - begin; - result := RESULT_ERROR; - set_last_error(e.Message); - end; - end; - - len := Length(TPA); - if len > 0 then - result := RESULT_OK - else - begin - setlength(tpa, 0); - exit(RESULT_FALSE); - end; - - ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); - setlength(TPA, 0); + try + res := C.MFinder.FindDTMs(C.MDTMs.DTM[DTMi], TPA, x1, y1, x2, y2); + except on e : Exception do + begin; + result := RESULT_ERROR; + set_last_error(e.Message); + end; + end; + + len := Length(TPA); + if len > 0 then + result := RESULT_OK + else + begin + setlength(tpa, 0); + exit(RESULT_FALSE); + end; + + ptr := array_to_ptr(Pointer(@TPA[0]), len, sizeof(TPoint)); + setlength(TPA, 0); end; function set_array_target(C: TClient; Arr: PRGB32; Size: TPoint): integer; cdecl; begin - if not assigned(Arr) then + if not assigned(Arr) then + begin + set_last_error('Arr is not assigned'); + exit(RESULT_FALSE); + end; + + try + C.IOManager.SetTarget(Arr, Size); + result := RESULT_OK; + except on e : Exception do begin - set_last_error('Arr is not assigned'); - exit(RESULT_FALSE); - end; - - try - C.IOManager.SetTarget(Arr, Size); - result := RESULT_OK; - except on e : Exception do - begin; - set_last_error(e.message); - result := RESULT_FALSE; - end; + set_last_error(e.message); + result := RESULT_FALSE; end; + end; end; exports From cdb89a1802fb45583e6d49a171c0b50d34a625d5 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 13:12:21 +0200 Subject: [PATCH 24/37] MMLCore: FindBitmapToleranceIn cts rewrite. --- Units/MMLCore/finder.pas | 99 +++++++++++++++++++++++++++++----------- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 99a916d..238b70a 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -128,6 +128,9 @@ type end; PCTS2Info = ^TCTS2Info; + TCTSInfo = Pointer; + TCTSInfoArray = Array of TCTSInfo; + TCTSInfo2DArray = Array of TCTSInfoArray; TCTSCompareFunction = function (ctsInfo: Pointer; C2: PRGB32): boolean; @@ -462,6 +465,45 @@ begin raise Exception.Create('Free_CTSInfo: Invalid TCTSInfo passed'); end; + +function Create_CTSInfo2DArray(cts, xs, ys, xe, ye: integer; bmp: TMufasaBitmap; + Tolerance: Integer; hueMod, satMod: Extended): TCTSInfo2DArray; +var + x, y, w: integer; +begin + setlength(result,ye-ys+1,xe-xs+1); + w := bmp.width; + for y := ys to ye do + for x := xs to xe do + begin + { This is kinda ugly. We call RGBToColor() here only to call ColorToRGB() + later again in Create_CTSInfo) } + result[y-ys][x-xs] := Create_CTSInfo(cts, + rgbtocolor(bmp.fdata[y*w+x].R, bmp.fdata[y*w+x].G, + bmp.fdata[y*w+x].B), + Tolerance, hueMod, satMod); + end; +end; + +procedure Free_CTSInfoArray(i: TCTSInfoArray); +var + c: integer; +begin + for c := high(i) downto 0 do + Free_CTSInfo(i[c]); + SetLength(i, 0); +end; + +procedure Free_CTSInfo2DArray(i: TCTSInfo2DArray); +var + x, y: integer; +begin + for y := high(i) downto 0 do + for x := high(i[y]) downto 0 do + Free_CTSInfo(i[y][x]); + SetLength(i, 0); +end; + function Get_CTSCompare(cts: Integer): TCTSCompareFunction; begin @@ -546,30 +588,29 @@ var PtrInc: Integer; clR, clG, clB : byte; dX, dY, xx, yy: Integer; - h,s,l,hmod,smod : extended; - Ccts : integer; + + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; begin Result := 0; DefaultOperations(xs, ys, xe, ye); + dX := xe - xs; dY := ye - ys; - ColorToRGB(Color, clR, clG, clB); + PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; - CCts := Self.CTS; result := 0; - if cts = 2 then - begin; - RGBToHSL(clR,clG,clB,h,s,l); - hmod := Self.hueMod; - smod := Self.satMod; - end; + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tolerance, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + for yy := ys to ye do begin; for xx := xs to xe do - begin; - if ColorSame(CCts,Tolerance,clR,clG,clB,Ptr^.r,Ptr^.g,Ptr^.b,H,S,L,hmod,smod) then + begin + if compare(ctsinfo, Ptr) then inc(result); Inc(Ptr); end; @@ -1008,7 +1049,7 @@ var dX, dY, clR, clG, clB: Integer; xx, yy: integer; compare: TCTSCompareFunction; - ctsinfo: Pointer; + ctsinfo: TCTSInfo; label Hit; @@ -1141,7 +1182,7 @@ var xx, yy: integer; compare: TCTSCompareFunction; - ctsinfo: Pointer; + ctsinfo: TCTSInfo; { procedure cts3; begin @@ -1184,9 +1225,6 @@ begin ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); compare := Get_CTSCompare(Self.CTS); - if cts = 1 then - tol := tol * tol; - for yy := ys to ye do begin for xx := xs to xe do @@ -1350,7 +1388,7 @@ var dX, dY, SpiralHi, i: Integer; compare: TCTSCompareFunction; - ctsinfo: Pointer; + ctsinfo: TCTSInfo; begin Result := false; @@ -1591,7 +1629,6 @@ begin TClient(Client).IOManager.FreeReturnData; end; - { TODO: Implement HSLRows? } @@ -1605,9 +1642,11 @@ var xBmp,yBmp : integer; tmpY : integer; dX, dY, xx, yy: Integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1630,10 +1669,10 @@ begin //Heck our bitmap cannot be outside the search area dX := dX - bmpW; dY := dY - bmpH; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, xs, ys, xe, ye, bitmap, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); @@ -1645,21 +1684,29 @@ begin tmpY := yBmp + yy; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + xx]) then + { if not ColorSame(CCTS,tolerance, BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, - H,S,L,HMod,SMod) then + H,S,L,HMod,SMod) then } goto NotFoundBmp; end; + //We did find the Bmp, otherwise we would be at the part below + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; + x := xx + xs; y := yy + ys; result := true; exit; NotFoundBmp: end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; From daff307f3d8062e1643a99ca2a8940c6199c20c0 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 13:46:10 +0200 Subject: [PATCH 25/37] Tests: Add BmpBench. --- Tests/PS/bmpbench.simba | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Tests/PS/bmpbench.simba diff --git a/Tests/PS/bmpbench.simba b/Tests/PS/bmpbench.simba new file mode 100644 index 0000000..dc9acea --- /dev/null +++ b/Tests/PS/bmpbench.simba @@ -0,0 +1,34 @@ +program new; +//http://farm4.static.flickr.com/3067/2612399892_7df428d482.jpg +{Make the above bitmap your target} +var + Bmp : integer; + x,y : integer; + w,h : integer; + t, i, c: integer; +begin + Bmp := createBitmap(15, 10); + FastDrawClear(bmp, clRed); + GetClientDimensions(w,h); + writeln(w); + writeln(h); + + for c := 0 to 2 do + begin + writeln('cts: ' + inttostr(c)); + setcolortolerancespeed(c); + + t:=getsystemtime; + for i := 0 to 100 do + findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,10); + writeln((getsystemtime-t) / 100.0); + if findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,200) then + writeln('found'); + end; + + {if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,300) then + begin + writeln('found'); + MoveMouse(x,y); + end;} +end. From 0422f0eb5a89159c4019ec9066d7bae9dbfc267c Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 15:53:48 +0200 Subject: [PATCH 26/37] MML/Core: Fixes for FindBitmapToleranceIn. --- Units/MMLCore/finder.pas | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 238b70a..ef487d7 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -107,7 +107,6 @@ uses tpa, //TPABounds dtmutil; - type TCTS0Info = record B, G, R, A: byte; @@ -466,21 +465,24 @@ begin end; -function Create_CTSInfo2DArray(cts, xs, ys, xe, ye: integer; bmp: TMufasaBitmap; +function Create_CTSInfo2DArray(cts, w, h: integer; bmp: TMufasaBitmap; Tolerance: Integer; hueMod, satMod: Extended): TCTSInfo2DArray; var - x, y, w: integer; + x, y: integer; + data: PRGB32; begin - setlength(result,ye-ys+1,xe-xs+1); - w := bmp.width; - for y := ys to ye do - for x := xs to xe do + setlength(result,h+1,w+1); + + data := bmp.fdata; + + for y := 0 to h do + for x := 0 to w do begin { This is kinda ugly. We call RGBToColor() here only to call ColorToRGB() later again in Create_CTSInfo) } - result[y-ys][x-xs] := Create_CTSInfo(cts, - rgbtocolor(bmp.fdata[y*w+x].R, bmp.fdata[y*w+x].G, - bmp.fdata[y*w+x].B), + result[y][x] := Create_CTSInfo(cts, + rgbtocolor(data[y*w+x].R, data[y*w+x].G, + data[y*w+x].B), Tolerance, hueMod, satMod); end; end; @@ -1670,7 +1672,7 @@ begin dX := dX - bmpW; dY := dY - bmpH; - ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, xs, ys, xe, ye, bitmap, + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, bitmap, Tolerance, self.hueMod, self.satMod); compare := Get_CTSCompare(Self.CTS); From 3b939443e81540dfac64c22c10558fd9d0bac7cd Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 19:10:10 +0200 Subject: [PATCH 27/37] MML/Core: FindBitmapToleranceIn is nearly finished. Speed is nice, results are not accurate yet. I probably missed something when pre-loading the data. --- Units/MMLCore/finder.pas | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index ef487d7..81d172f 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -423,7 +423,7 @@ end; { } function Create_CTSInfo(cts: integer; Color, Tol: Integer; - hueMod, satMod: extended): Pointer; + hueMod, satMod: extended): Pointer; overload; var R, G, B: Integer; H, S, L: Integer; @@ -456,6 +456,16 @@ begin end; end; + +function Create_CTSInfo(cts: integer; R, G, B, Tol: Integer; + hueMod, satMod: extended): Pointer; overload; + +var Color: Integer; + +begin + Color := RGBToColor(R, G, B); + Result := Create_CTSInfo(cts, Color, Tol, hueMod, satMod); +end; procedure Free_CTSInfo(i: Pointer); begin if assigned(i) then @@ -473,16 +483,14 @@ var begin setlength(result,h+1,w+1); + w := bmp.width; data := bmp.fdata; for y := 0 to h do for x := 0 to w do begin - { This is kinda ugly. We call RGBToColor() here only to call ColorToRGB() - later again in Create_CTSInfo) } result[y][x] := Create_CTSInfo(cts, - rgbtocolor(data[y*w+x].R, data[y*w+x].G, - data[y*w+x].B), + data[y*w+x].R, data[y*w+x].G, data[y*w+x].B, Tolerance, hueMod, satMod); end; end; @@ -1676,6 +1684,25 @@ begin Tolerance, self.hueMod, self.satMod); compare := Get_CTSCompare(Self.CTS); +// for yBmp := 0 to BmpH do +// begin +// tmpY := yBmp + yy; +// for xBmp := 0 to BmpW do +// begin +// writeln('BmpRowData: ' + IntToStr(BmpRowData[yBmp][xBmp].R) + ', ' + +// IntToStr(BmpRowData[yBmp][xBmp].G) +// + ', ' + IntToStr(BmpRowData[yBmp][xBmp].B)); +// +// case self.cts of +// 0, 1: writeln('ctsinfo: ' + +// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).R) + ', ' + +// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).G) + ', ' + +// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).B)); +// end; +// +// end; +// end; + //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); for yy := 0 to dY do From 6f32e21291a863e9187b05e38a940a4921105b37 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 20:08:17 +0200 Subject: [PATCH 28/37] MML/Core: FindBitmapToleranceIn seems to work. --- Units/MMLCore/finder.pas | 44 +++++++++------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 81d172f..aea425a 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -441,7 +441,8 @@ begin Result := AllocMem(SizeOf(TCTS1Info)); ColorToRGB(Color, PCTS1Info(Result)^.R, PCTS1Info(Result)^.G, PCTS1Info(Result)^.B); - PCTS1Info(Result)^.Tol := Tol*Tol; + + PCTS1Info(Result)^.Tol := Tol * Tol; end; 2: begin @@ -466,6 +467,7 @@ begin Color := RGBToColor(R, G, B); Result := Create_CTSInfo(cts, Color, Tol, hueMod, satMod); end; + procedure Free_CTSInfo(i: Pointer); begin if assigned(i) then @@ -475,22 +477,18 @@ begin end; -function Create_CTSInfo2DArray(cts, w, h: integer; bmp: TMufasaBitmap; +function Create_CTSInfo2DArray(cts, w, h: integer; data: TPRGB32Array; Tolerance: Integer; hueMod, satMod: Extended): TCTSInfo2DArray; var x, y: integer; - data: PRGB32; begin - setlength(result,h+1,w+1); - - w := bmp.width; - data := bmp.fdata; + SetLength(Result,h+1,w+1); for y := 0 to h do for x := 0 to w do begin - result[y][x] := Create_CTSInfo(cts, - data[y*w+x].R, data[y*w+x].G, data[y*w+x].B, + Result[y][x] := Create_CTSInfo(cts, + data[y][x].R, data[y][x].G, data[y][x].B, Tolerance, hueMod, satMod); end; end; @@ -1639,9 +1637,6 @@ begin TClient(Client).IOManager.FreeReturnData; end; -{ - TODO: Implement HSLRows? -} function TMFinder.FindBitmapToleranceIn(bitmap: TMufasaBitmap; out x, y: Integer; xs, ys, xe, ye: Integer; tolerance: Integer): Boolean; var @@ -1653,12 +1648,13 @@ var tmpY : integer; dX, dY, xx, yy: Integer; SkipCoords : T2DBoolArray; + a: TRGB32; ctsinfoarray: TCTSInfo2DArray; compare: TCTSCompareFunction; label NotFoundBmp; - { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } + { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } begin Result := false; @@ -1680,29 +1676,10 @@ begin dX := dX - bmpW; dY := dY - bmpH; - ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, bitmap, + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, Tolerance, self.hueMod, self.satMod); compare := Get_CTSCompare(Self.CTS); -// for yBmp := 0 to BmpH do -// begin -// tmpY := yBmp + yy; -// for xBmp := 0 to BmpW do -// begin -// writeln('BmpRowData: ' + IntToStr(BmpRowData[yBmp][xBmp].R) + ', ' + -// IntToStr(BmpRowData[yBmp][xBmp].G) -// + ', ' + IntToStr(BmpRowData[yBmp][xBmp].B)); -// -// case self.cts of -// 0, 1: writeln('ctsinfo: ' + -// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).R) + ', ' + -// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).G) + ', ' + -// IntToStr(TCTS1Info(ctsinfoarray[yBmp][xBmp]).B)); -// end; -// -// end; -// end; - //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); for yy := 0 to dY do @@ -1720,7 +1697,6 @@ begin MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, H,S,L,HMod,SMod) then } goto NotFoundBmp; - end; //We did find the Bmp, otherwise we would be at the part below From 013daccf0770abc0d7fc1f2b8c07a2e6d2419dd8 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 20:09:31 +0200 Subject: [PATCH 29/37] MML/Core: Cleanup. --- Units/MMLCore/finder.pas | 1 - 1 file changed, 1 deletion(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index aea425a..9a01486 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -1648,7 +1648,6 @@ var tmpY : integer; dX, dY, xx, yy: Integer; SkipCoords : T2DBoolArray; - a: TRGB32; ctsinfoarray: TCTSInfo2DArray; compare: TCTSCompareFunction; From 55b0435a4e77206d018793acebdd988968218a3a Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Sat, 30 Jul 2011 20:27:54 +0200 Subject: [PATCH 30/37] Tests: Update BmpBench. --- Tests/PS/bmpbench.simba | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Tests/PS/bmpbench.simba b/Tests/PS/bmpbench.simba index dc9acea..134b738 100644 --- a/Tests/PS/bmpbench.simba +++ b/Tests/PS/bmpbench.simba @@ -1,6 +1,5 @@ program new; -//http://farm4.static.flickr.com/3067/2612399892_7df428d482.jpg -{Make the above bitmap your target} + var Bmp : integer; x,y : integer; @@ -19,11 +18,14 @@ begin setcolortolerancespeed(c); t:=getsystemtime; - for i := 0 to 100 do + for i := 0 to 10 do findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,10); - writeln((getsystemtime-t) / 100.0); - if findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,200) then + writeln((getsystemtime-t) / 10.0); + if findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,10) then + begin writeln('found'); + movemouse(x,y); + end; end; {if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,300) then From 464b90d42bccf931451054b350ac53402aec4192 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 13:58:49 +0200 Subject: [PATCH 31/37] MMLCore/finder: Small cleanup. --- Units/MMLCore/finder.pas | 53 ++++++++++++---------------------------- 1 file changed, 15 insertions(+), 38 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 9a01486..87b16a8 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -431,28 +431,28 @@ begin case cts of 0: begin - Result := AllocMem(SizeOf(TCTS0Info)); - ColorToRGB(Color, PCTS0Info(Result)^.R, PCTS0Info(Result)^.G, - PCTS0Info(Result)^.B); - PCTS0Info(Result)^.Tol := Tol; + Result := AllocMem(SizeOf(TCTS0Info)); + ColorToRGB(Color, PCTS0Info(Result)^.R, PCTS0Info(Result)^.G, + PCTS0Info(Result)^.B); + PCTS0Info(Result)^.Tol := Tol; end; 1: begin - Result := AllocMem(SizeOf(TCTS1Info)); - ColorToRGB(Color, PCTS1Info(Result)^.R, PCTS1Info(Result)^.G, - PCTS1Info(Result)^.B); + Result := AllocMem(SizeOf(TCTS1Info)); + ColorToRGB(Color, PCTS1Info(Result)^.R, PCTS1Info(Result)^.G, + PCTS1Info(Result)^.B); - PCTS1Info(Result)^.Tol := Tol * Tol; + PCTS1Info(Result)^.Tol := Tol * Tol; end; 2: begin - Result := AllocMem(SizeOf(TCTS2Info)); - ColorToRGB(Color, R, G, B); - RGBToHSL(R, G, B, PCTS2Info(Result)^.H, PCTS2Info(Result)^.S, - PCTS2Info(Result)^.L); - PCTS2Info(Result)^.hueMod := Tol * hueMod; - PCTS2Info(Result)^.satMod := Tol * satMod; - PCTS2Info(Result)^.Tol := Tol; + Result := AllocMem(SizeOf(TCTS2Info)); + ColorToRGB(Color, R, G, B); + RGBToHSL(R, G, B, PCTS2Info(Result)^.H, PCTS2Info(Result)^.S, + PCTS2Info(Result)^.L); + PCTS2Info(Result)^.hueMod := Tol * hueMod; + PCTS2Info(Result)^.satMod := Tol * satMod; + PCTS2Info(Result)^.Tol := Tol; end; end; end; @@ -1192,29 +1192,6 @@ var compare: TCTSCompareFunction; ctsinfo: TCTSInfo; - { procedure cts3; - begin - RGBToXYZ(clR, clG, clB, X, Y, Z); - XYZToCieLab(X, Y, Z, L1, A1, B1); - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToXYZ(Ptr^.R, Ptr^.G, Ptr^.B, X, Y, Z); - XYZtoCIELab(X, Y, Z, L2, A2, B2); - if Sqrt(sqr(L1 - L2) + sqr(A1 - A2) + - sqr(B1 - B2)) <= Tol then - begin - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - Inc(c); - end; - Inc(Ptr) - end; - Inc(Ptr, PtrInc); - end; - end; } - begin Result := false; DefaultOperations(xs,ys,xe,ye); From 56e01c67fa031b36647a4f4e36b736c3f664d779 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 16:16:19 +0200 Subject: [PATCH 32/37] MML/Finder: CTS: Bitmap+Color functions done. Only DTM to go. --- Units/MMLCore/finder.pas | 157 +++++++++++++++++++++------------------ 1 file changed, 83 insertions(+), 74 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 87b16a8..cdc88de 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -38,8 +38,8 @@ uses Should be 100% OS independant, as all OS dependant code is in the IO Manager. Let's try not to use any OS-specific defines here? ;) - - Benchmarks with FindBitmapToleranceIn on _very_ high tolerance! + TODO: Check that each procedure calling Create_CTSInfo also calls + Free_CTSInfo(). } type @@ -624,6 +624,8 @@ begin end; Inc(Ptr, PtrInc) end; + + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -764,48 +766,10 @@ var RowData : TPRGB32Array; dX, dY, clR, clG, clB,i,Hispiral: Integer; - function cts0: integer; - var j: integer; - begin - for j := 0 to HiSpiral do - if ((abs(clB-RowData[ClientTPA[j].y][ClientTPA[j].x].B) <= Tol) and - (abs(clG-RowData[ClientTPA[j].y][ClientTPA[j].x].G) <= Tol) and - (Abs(clR-RowData[ClientTPA[j].y][ClientTPA[j].x].R) <= Tol)) then - exit(j); - exit(-1); - end; - - function cts1: integer; - var j: integer; - begin - Tol := Sqr(Tol); - for j := 0 to HiSpiral do - if (sqr(clB - RowData[ClientTPA[j].y][ClientTPA[j].x].B) + - sqr(clG - RowData[ClientTPA[j].y][ClientTPA[j].x].G) + - sqr(clR-RowData[ClientTPA[j].y][ClientTPA[j].x].R)) <= Tol then - exit(j); - exit(-1); - end; - - function cts2: integer; - var j: integer; - HueXTol, SatXTol: Extended; - H1, S1, L1, H2, S2, L2: Extended; - begin - RGBToHSL(clR,clG,clB,H1,S1,L1); - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for j := 0 to HiSpiral do - begin - RGBToHSL(RowData[ClientTPA[j].y][ClientTPA[j].x].R, - RowData[ClientTPA[j].y][ClientTPA[j].x].G, - RowData[ClientTPA[j].y][ClientTPA[j].x].B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - exit(j); - end; - - exit(-1); - end; +var + j: integer; + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; begin Result := false; @@ -824,11 +788,22 @@ begin //Load the spiral path LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); HiSpiral := (dy+1) * (dx + 1) -1; - case CTS of - 0: i := cts0(); - 1: i := cts1(); - 2: i := cts2(); + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + + i := -1; + for j := 0 to HiSpiral do + begin + if compare(ctsinfo, @RowData[ClientTPA[j].y][ClientTPA[j].x]) then + begin + i := j; + break; + end; end; + + Free_CTSInfo(ctsinfo); + if i = -1 then begin Result := False; @@ -1092,6 +1067,7 @@ begin end; Result := False; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; Exit; @@ -1099,6 +1075,7 @@ begin Result := True; x := xx; y := yy; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -1111,8 +1088,13 @@ var clR, clG, clB : Byte; H1, S1, L1: Extended; NotFound : Boolean; + + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; + label Hit; + begin Result := false; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) @@ -1132,13 +1114,17 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; Count := 0; + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + for yy := ys to ye do begin; for xx := xs to xe do begin; NotFound := False; // Colour comparison here. - if ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then + if compare(ctsinfo, Ptr) then begin Before := Ptr; for fy := yy to ye do @@ -1146,7 +1132,7 @@ begin for fx := xx to xe do begin Inc(Ptr); - if not ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then + if compare(ctsinfo, Ptr) then begin NotFound := True; Break; @@ -1170,6 +1156,7 @@ begin end; Result := False; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; Exit; @@ -1177,6 +1164,7 @@ begin Result := True; x := xx; y := yy; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -1668,10 +1656,6 @@ begin if not SkipCoords[yBmp][xBmp] then if not compare(ctsinfoarray[yBmp][xBmp], @MainRowData[tmpY][xBmp + xx]) then - { if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, - H,S,L,HMod,SMod) then } goto NotFoundBmp; end; @@ -1683,7 +1667,7 @@ begin x := xx + xs; y := yy + ys; result := true; - exit; + Exit; NotFoundBmp: end; @@ -1766,6 +1750,10 @@ var CCTS : integer; H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1791,9 +1779,11 @@ begin //Load the spiral into memory LoadSpiralPath(x-xs,y-ys,0,0,dX,dY); HiSpiral := (dx+1) * (dy+1) - 1; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; + + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); @@ -1804,21 +1794,23 @@ begin tmpY := yBmp + ClientTPA[i].y; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].B, - H,S,L,HMod,SMod) then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + ClientTPA[i].x]) then goto NotFoundBmp; end; //We did find the Bmp, otherwise we would be at the part below + + Free_CTSInfo2DArray(ctsinfoarray); + TClient(Client).IOManager.FreeReturnData; + x := ClientTPA[i].x + xs; y := ClientTPA[i].y + ys; result := true; exit; NotFoundBmp: end; + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; @@ -1836,6 +1828,10 @@ var CCTS : integer; H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1861,10 +1857,12 @@ begin //Load the spiral into memory LoadSpiralPath(x-xs,y-ys,0,0,dX,dY); HiSpiral := (dx+1) * (dy+1) - 1; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; FoundC := 0; + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); for i := 0 to HiSpiral do @@ -1874,11 +1872,8 @@ begin tmpY := yBmp + ClientTPA[i].y; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].B, - H,S,L,HMod,SMod) then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + ClientTPA[i].x]) then goto NotFoundBmp; end; @@ -1894,6 +1889,8 @@ begin SetLength(Points,FoundC); Move(ClientTPA[0], Points[0], FoundC * SizeOf(TPoint)); end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; @@ -1916,6 +1913,10 @@ var TotalC : integer; SkipCoords : T2DBoolArray; PointsLeft : T2DIntArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label FoundBMPPoint, Madness; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1943,6 +1944,11 @@ begin Accuracy := 0; BestCount := -1; BestPT := Point(-1,-1); + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + //Get the "skip coords". and PointsLeft (so we can calc whether we should stop searching or not ;-). CalculateBitmapSkipCoordsEx(Bitmap,SkipCoords,TotalC,PointsLeft); @@ -1969,8 +1975,8 @@ begin xEnd := Min(xx+range + xBmp,SearchdX); for RangeX := xStart to xEnd do begin; - if Sqrt(sqr(BmpRowData[yBmp][xBmp].R - MainRowdata[RangeY][RangeX].R) + sqr(BmpRowData[yBmp][xBmp].G - MainRowdata[RangeY][RangeX].G) - +sqr(BmpRowData[yBmp][xBmp].B - MainRowdata[RangeY][RangeX].B)) <= tolerance then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[rangeY][rangeX]) then goto FoundBMPPoint; end; end; @@ -1988,7 +1994,8 @@ begin BestCount := GoodCount; BestPT := Point(xx+xs,yy+ys); if GoodCount = TotalC then - begin; + begin + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; x := BestPT.x; y := BestPT.y; @@ -1997,6 +2004,8 @@ begin end; end; end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; if BestCount = 0 then Exit; From a621a6e8daf3a4ab6e177ee2ae86808bbb7633fb Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 18:13:36 +0200 Subject: [PATCH 33/37] MML/Finder: FindDTMs rework done. --- Units/MMLCore/finder.pas | 64 ++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index cdc88de..c28742e 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -476,7 +476,24 @@ begin raise Exception.Create('Free_CTSInfo: Invalid TCTSInfo passed'); end; +{ TODO: Not universal, mainly for DTM } +function Create_CTSInfoArray(cts: integer; color, tolerance: array of integer; + hueMod, satMod: extended): TCTSInfoArray; +var + i: integer; +begin + if length(color) <> length(tolerance) then + raise Exception.Create('Create_CTSInfoArray: Length(Color) <>' + +' Length(Tolerance'); + SetLength(Result, Length(color)); + + for i := High(result) downto 0 do + result := Create_CTSInfo(cts, color[i], tolerance[i], hueMod, satMod); +end; + + +{ TODO: Not universal, mainly for Bitmap } function Create_CTSInfo2DArray(cts, w, h: integer; data: TPRGB32Array; Tolerance: Integer; hueMod, satMod: Extended): TCTSInfo2DArray; var @@ -486,11 +503,9 @@ begin for y := 0 to h do for x := 0 to w do - begin Result[y][x] := Create_CTSInfo(cts, data[y][x].R, data[y][x].G, data[y][x].B, Tolerance, hueMod, satMod); - end; end; procedure Free_CTSInfoArray(i: TCTSInfoArray); @@ -498,7 +513,7 @@ var c: integer; begin for c := high(i) downto 0 do - Free_CTSInfo(i[c]); + Free_CTSInfo(i[c]); SetLength(i, 0); end; @@ -2040,16 +2055,9 @@ end; //MaxToFind, if it's < 1 it won't stop looking function TMFinder.FindDTMs(DTM: TMDTM; out Points: TPointArray; x1, y1, x2, y2, maxToFind: Integer): Boolean; var - //Cache DTM stuff - Len : integer; //Len of the points - DPoints : PMDTMPoint; //DTM Points - // Colours of DTMs - clR,clG,clB : array of byte; - - //Similar colors stuff - hh,ss,ll: array of extended; - hmod,smod: extended; - Ccts : integer; + //Cache DTM stuff + Len : integer; //Len of the points + DPoints : PMDTMPoint; //DTM Points // Bitwise b: Array of Array of Integer; @@ -2077,11 +2085,13 @@ var goodPoints: Array of Boolean; + col_arr, tol_arr: Array of Integer; + ctsinfoarray: TCTSInfoArray; + compare: TCTSCompareFunction; + label theEnd; label AnotherLoopEnd; - - begin // Is the area valid? DefaultOperations(x1, y1, x2, y2); @@ -2113,21 +2123,15 @@ begin end; // C = DTM.C - SetLength(clR,Len); - SetLength(clG,Len); - SetLength(clB,Len); for i := 0 to Len - 1 do - ColorToRGB(DPoints[i].c,clR[i],clG[i],clB[i]); + begin + col_arr[i] := DPoints[i].c; + tol_arr[i] := DPoints[i].t; + end; - SetLength(hh,Len); - SetLength(ss,Len); - SetLength(ll,Len); - for i := 0 to Len - 1 do - ColorToHSL(DPoints[i].c,hh[i],ss[i],ll[i]); - - GetToleranceSpeed2Modifiers(hMod, sMod); - - ccts := CTS; + ctsinfoarray := Create_CTSInfoArray(Self.CTS, + col_arr, tol_arr, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); @@ -2165,7 +2169,7 @@ begin // Checking point i now. (Store that we matched it) ch[xxx][yyy]:= ch[xxx][yyy] or (1 shl i); // if SimilarColors(dtm.c[i], rgbtocolor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), DPoints[i].t) then - if ColorSame(ccts,DPoints[i].t,clR[i],clG[i],clB[i],cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B,hh[i],ss[i],ll[i],hmod,smod) then + if compare(ctsinfoarray[i], @cd[yyy][xxx]) then b[xxx][yyy] := b[xxx][yyy] or (1 shl i); end; @@ -2194,6 +2198,8 @@ begin AnotherLoopEnd: end; TheEnd: + + Free_CTSInfoArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; SetLength(Points, pc); From 1fc33752e4e75aa3c96b7f24bba53ee98dfc60ed Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 19:04:16 +0200 Subject: [PATCH 34/37] MML/Finder: FindDTMsRotated rework. --- Units/MMLCore/finder.pas | 67 +++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 36 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index c28742e..9acc558 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -2122,6 +2122,9 @@ begin FillChar(b[i][0], SizeOf(Integer) * (H+1), 0); end; + // Retreive Client Data. + PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + // C = DTM.C for i := 0 to Len - 1 do begin @@ -2133,9 +2136,6 @@ begin col_arr, tol_arr, self.hueMod, self.satMod); compare := Get_CTSCompare(Self.CTS); - // Retreive Client Data. - PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); - cd := CalculateRowPtrs(PtrData, h + 1); //CD starts at 0,0.. We must adjust the MA, since this is still based on the xs,ys,xe,ye box. MA.x1 := MA.x1 - x1; @@ -2216,14 +2216,15 @@ var begin FindDTMsRotated(dtm, P, x1, y1, x2, y2, sAngle, eAngle, aStep, F,Alternating,1); if Length(P) = 0 then - exit(false); + exit(False); aFound := F[0][0]; x := P[0].x; y := P[0].y; Exit(True); end; -procedure RotPoints_DTM(const P: TPointArray;var RotTPA : TPointArray; const A: Extended); +procedure RotPoints_DTM(const P: TPointArray;var RotTPA : TPointArray; const A: + Extended); inline; var I, L: Integer; begin @@ -2237,18 +2238,11 @@ end; function TMFinder.FindDTMsRotated(DTM: TMDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray;Alternating : boolean; maxToFind: Integer): Boolean; var - //Cached variables - Len : integer; - DPoints : PMDTMPoint; - DTPA : TPointArray; - RotTPA: TPointArray; - // Colours of DTMs - clR,clG,clB : array of byte; - - //Similar colors stuff - hh,ss,ll: array of extended; - hmod,smod: extended; - Ccts : integer; + //Cached variables + Len : integer; + DPoints : PMDTMPoint; + DTPA : TPointArray; + RotTPA: TPointArray; // Bitwise b: Array of Array of Integer; @@ -2283,6 +2277,10 @@ var goodPoints: Array of Boolean; s: extended; + col_arr, tol_arr: Array of Integer; + ctsinfoarray: TCTSInfoArray; + compare: TCTSCompareFunction; + label theEnd; label AnotherLoopEnd; @@ -2318,20 +2316,6 @@ begin FillChar(ch[i][0], SizeOf(Integer) * (H+1), 0); end; - // Convert colors to there components - SetLength(clR,Len); - SetLength(clG,Len); - SetLength(clB,Len); - for i := 0 to Len - 1 do - ColorToRGB(DPoints[i].c,clR[i],clG[i],clB[i]); - //Compiler hints - - SetLength(hh,Len); - SetLength(ss,Len); - SetLength(ll,Len); - for i := 0 to Len - 1 do - ColorToHSL(DPoints[i].c,hh[i],ss[i],ll[i]); - { When we search for a rotated DTM, everything is the same, except the coordinates.. Therefore we create a TPA of the 'original' DTM, containing all the Points. @@ -2341,12 +2325,20 @@ begin for i := 0 to len-1 do DTPA[i] := Point(DPoints[i].x,DPoints[i].y); - GetToleranceSpeed2Modifiers(hMod, sMod); - ccts := CTS; - // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + // C = DTM.C + for i := 0 to Len - 1 do + begin + col_arr[i] := DPoints[i].c; + tol_arr[i] := DPoints[i].t; + end; + + ctsinfoarray := Create_CTSInfoArray(Self.CTS, + col_arr, tol_arr, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + cd := CalculateRowPtrs(PtrData, h + 1); SetLength(aFound, 0); SetLength(Points, 0); @@ -2392,7 +2384,7 @@ begin // Checking point i now. (Store that we matched it) ch[xxx][yyy]:= ch[xxx][yyy] or (1 shl i); - if ColorSame(ccts,DPoints[i].t,clR[i],clG[i],clB[i],cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B,hh[i],ss[i],ll[i],hmod,smod) then + if compare(ctsinfoarray[i], cd[yyy][xxx]) then b[xxx][yyy] := b[xxx][yyy] or (1 shl i); end; @@ -2436,7 +2428,10 @@ begin s := s + aStep; end; TheEnd: - TClient(Client).IOManager.FreeReturnData; + + Free_CTSInfoArray(ctsinfoarray); + TClient(Client).IOManager.FreeReturnData; + Result := (pc > 0); { Don't forget to pre calculate the rotated points at the start. Saves a lot of rotatepoint() calls. } From f159f20bc2ce51414f0af47d9e17f4ed337077bb Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 19:05:03 +0200 Subject: [PATCH 35/37] MML/Finder: Fix FindDTMsRotated. --- Units/MMLCore/finder.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 9acc558..1a0df67 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -2384,7 +2384,7 @@ begin // Checking point i now. (Store that we matched it) ch[xxx][yyy]:= ch[xxx][yyy] or (1 shl i); - if compare(ctsinfoarray[i], cd[yyy][xxx]) then + if compare(ctsinfoarray[i], @cd[yyy][xxx]) then b[xxx][yyy] := b[xxx][yyy] or (1 shl i); end; From d1e3645ee5cc5793392ab0f5c178ef018a84adb0 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Mon, 1 Aug 2011 19:08:23 +0200 Subject: [PATCH 36/37] MML/Finder: Fix all compiler hints + bug. --- Units/MMLCore/finder.pas | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index 1a0df67..432dd89 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -426,7 +426,6 @@ function Create_CTSInfo(cts: integer; Color, Tol: Integer; hueMod, satMod: extended): Pointer; overload; var R, G, B: Integer; - H, S, L: Integer; begin case cts of 0: @@ -609,7 +608,6 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc: Integer; - clR, clG, clB : byte; dX, dY, xx, yy: Integer; compare: TCTSCompareFunction; @@ -1044,7 +1042,7 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc: Integer; - dX, dY, clR, clG, clB: Integer; + dX, dY: Integer; xx, yy: integer; compare: TCTSCompareFunction; ctsinfo: TCTSInfo; @@ -1189,7 +1187,7 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc,C: Integer; - dX, dY, clR, clG, clB: Integer; + dX, dY: Integer; xx, yy: integer; compare: TCTSCompareFunction; @@ -1762,8 +1760,6 @@ var xBmp,yBmp : integer; tmpY : integer; dX, dY, i,HiSpiral: Integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; ctsinfoarray: TCTSInfo2DArray; @@ -1840,8 +1836,6 @@ var tmpY : integer; dX, dY, i,HiSpiral: Integer; FoundC : integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; ctsinfoarray: TCTSInfo2DArray; @@ -2125,6 +2119,8 @@ begin // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + SetLength(col_arr, Len); + SetLength(tol_arr, Len); // C = DTM.C for i := 0 to Len - 1 do begin @@ -2272,7 +2268,6 @@ var // point count pc: Integer = 0; - ac: Integer = 0; goodPoints: Array of Boolean; s: extended; @@ -2328,6 +2323,8 @@ begin // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + SetLength(col_arr, Len); + SetLength(tol_arr, Len); // C = DTM.C for i := 0 to Len - 1 do begin @@ -2416,7 +2413,6 @@ begin goto theEnd; AnotherLoopEnd: end; - ac := 0; if Alternating then begin if AngleSteps mod 2 = 0 then //This means it's an even number, thus we must add a positive step From 5b3e2a864b9f2e266766cc1a8fba5e157e862386 Mon Sep 17 00:00:00 2001 From: Merlijn Wajer Date: Thu, 4 Aug 2011 00:41:00 +0200 Subject: [PATCH 37/37] Merge new CTS/Finder system. Touches pretty much all the functions in finder.pas, so I expect a lot of functions to break. Tests will have to be written and results will have to be compared with Simba 0.97. Still, I think it's ready for merging to simba-next. Squashed commit of the following: commit d1e3645ee5cc5793392ab0f5c178ef018a84adb0 Author: Merlijn Wajer Date: Mon Aug 1 19:08:23 2011 +0200 MML/Finder: Fix all compiler hints + bug. commit f159f20bc2ce51414f0af47d9e17f4ed337077bb Author: Merlijn Wajer Date: Mon Aug 1 19:05:03 2011 +0200 MML/Finder: Fix FindDTMsRotated. commit 1fc33752e4e75aa3c96b7f24bba53ee98dfc60ed Author: Merlijn Wajer Date: Mon Aug 1 19:04:16 2011 +0200 MML/Finder: FindDTMsRotated rework. commit a621a6e8daf3a4ab6e177ee2ae86808bbb7633fb Author: Merlijn Wajer Date: Mon Aug 1 18:13:36 2011 +0200 MML/Finder: FindDTMs rework done. commit 0b592eef86629fec6c791aed6cc0359c18586e62 Merge: 56e01c6 aaafd6b Author: Merlijn Wajer Date: Mon Aug 1 16:48:09 2011 +0200 Merge branch 'master' into cts-rework Conflicts: Units/MMLCore/finder.pas commit 56e01c67fa031b36647a4f4e36b736c3f664d779 Author: Merlijn Wajer Date: Mon Aug 1 16:16:19 2011 +0200 MML/Finder: CTS: Bitmap+Color functions done. Only DTM to go. commit 464b90d42bccf931451054b350ac53402aec4192 Author: Merlijn Wajer Date: Mon Aug 1 13:58:49 2011 +0200 MMLCore/finder: Small cleanup. commit 2414f60c083ace5ca1c1e1f8f8eb54b245b4f2ba Merge: 55b0435 a20a31a Author: Merlijn Wajer Date: Sun Jul 31 18:12:41 2011 +0200 Merge branch 'master' into cts-rework commit 55b0435a4e77206d018793acebdd988968218a3a Author: Merlijn Wajer Date: Sat Jul 30 20:27:54 2011 +0200 Tests: Update BmpBench. commit 013daccf0770abc0d7fc1f2b8c07a2e6d2419dd8 Author: Merlijn Wajer Date: Sat Jul 30 20:09:31 2011 +0200 MML/Core: Cleanup. commit 6f32e21291a863e9187b05e38a940a4921105b37 Author: Merlijn Wajer Date: Sat Jul 30 20:08:17 2011 +0200 MML/Core: FindBitmapToleranceIn seems to work. commit 3b939443e81540dfac64c22c10558fd9d0bac7cd Author: Merlijn Wajer Date: Sat Jul 30 19:10:10 2011 +0200 MML/Core: FindBitmapToleranceIn is nearly finished. Speed is nice, results are not accurate yet. I probably missed something when pre-loading the data. commit 0422f0eb5a89159c4019ec9066d7bae9dbfc267c Author: Merlijn Wajer Date: Sat Jul 30 15:53:48 2011 +0200 MML/Core: Fixes for FindBitmapToleranceIn. commit 65f4ae16edb75065fef8ff802580de6627501ac7 Merge: daff307 353d1f3 Author: Merlijn Wajer Date: Sat Jul 30 14:32:46 2011 +0200 Merge branch 'master' into cts-rework commit daff307f3d8062e1643a99ca2a8940c6199c20c0 Author: Merlijn Wajer Date: Sat Jul 30 13:46:10 2011 +0200 Tests: Add BmpBench. commit cdb89a1802fb45583e6d49a171c0b50d34a625d5 Author: Merlijn Wajer Date: Sat Jul 30 13:12:21 2011 +0200 MMLCore: FindBitmapToleranceIn cts rewrite. commit d0bd81c2e9e314ffe98bc58afdc35cd467090722 Merge: 3282636 da0de6e Author: Merlijn Wajer Date: Sat Jul 30 00:15:50 2011 +0200 Merge branch 'master' into cts-rework commit 32826361789890c8aaa65a06bebd022faabb6f05 Merge: 7c86003 a8cdf77 Author: Merlijn Wajer Date: Mon Jul 25 16:50:43 2011 +0200 Merge branch 'master' into cts-rework commit 7c8600311c1792c9411826040dc804860775a6be Merge: 153025f e0767cb Author: Merlijn Wajer Date: Sun Jul 24 00:14:53 2011 +0200 Merge branch 'master' into cts-rework Conflicts: Doc/sphinx/conf.py Doc/sphinx/libmml/intro.rst commit 153025f08035a1125010bd6b7bf62dca57f084a0 Author: Merlijn Wajer Date: Sun Jul 17 19:51:16 2011 +0200 libMML: Changed the indentation. commit 8abd502580fa782541095cdcb04cb3ba99f304cd Author: Merlijn Wajer Date: Sun Jul 17 19:37:33 2011 +0200 Documentation: Bump version to 820. commit 031654b3d1120de61fc3a5b7923656f6d0108e2d Author: Merlijn Wajer Date: Sun Jul 17 19:36:21 2011 +0200 Documentation: Initial libMML documentation. commit f91c9ffb0e31871c51995cf030bd811d76c8b438 Merge: f5c9690 989d077 Author: Merlijn Wajer Date: Thu Jul 7 12:00:58 2011 +0200 Merge branch 'master' into cts-rework commit f5c9690bee157f9e8dc82a7d23c5841629e8599c Author: Merlijn Wajer Date: Thu Jul 7 11:59:15 2011 +0200 Finder: More rework and cleanups. commit 79021409d05c24da797f73299744e588effd381c Author: Merlijn Wajer Date: Wed Jul 6 21:34:03 2011 +0200 Finder: CTS 2 fix. commit cda571dcb0a3f3f755a63978d07f2a25f83861a7 Author: Merlijn Wajer Date: Wed Jul 6 21:06:17 2011 +0200 Finder: Remote tolerance param. Cleanups. commit 733a8cbf320ca29f1edf60b9e29f1ae5c0d68b67 Author: Merlijn Wajer Date: Wed Jul 6 20:39:44 2011 +0200 Finder: More fixes. :-) commit e6b005b61f0a4c223d0e8c1f109d28aa48c0ad17 Author: Merlijn Wajer Date: Wed Jul 6 18:34:49 2011 +0200 Finder: CTS-rework fixes. commit 6f896b56a292098a1aef2ddb138ea65ce96ec6a3 Author: Merlijn Wajer Date: Wed Jul 6 18:15:33 2011 +0200 Finder: Start CTS rework. commit a63039914878e2eb40ff21a9c76f757b6e785716 Author: Merlijn Wajer Date: Wed Jul 6 13:01:22 2011 +0200 Small TODO update. commit 0e6bf83a5cf5fa9d319fe10276f3f2291025b543 Merge: f19fd6b f2873b1 Author: Merlijn Wajer Date: Wed Jul 6 12:59:09 2011 +0200 Merge branch 'master' into cts-rework commit f19fd6bf8d3589c196d063e1ff4962994606af55 Author: Merlijn Wajer Date: Sun Jul 3 20:42:14 2011 +0200 Simba/Doc: Add Raymond to doc. commit 451ab89db36cc9b0fa5508a56917291918a1127f Merge: 37183f5 35026bc Author: Merlijn Wajer Date: Sat Jul 2 14:48:43 2011 +0200 Merge branch 'master' into cts-rework commit 37183f5fd0baaa46f3726ce835f009153ef611d0 Merge: cca7b05 6873e72 Author: Merlijn Wajer Date: Tue Jun 28 22:10:02 2011 +0200 Merge branch 'master' into cts-rework commit cca7b052135c874064ae9277956a7d078a58dbaf Author: Merlijn Wajer Date: Thu Jun 16 17:03:14 2011 +0200 Add CTS 3 to FindColorsTolerance. Conflicts: Units/MMLCore/finder.pas commit c837d9b96057a58e4cd1a1d5efa241118e1e7d7d Author: Merlijn Wajer Date: Thu Jun 16 16:33:25 2011 +0200 CTS 3: Fix typo. commit 52db461f845694d89254c7f0ea5d5fecfc9764f7 Author: Merlijn Wajer Date: Mon Jun 6 16:06:17 2011 +0200 CTS 3: Now implement the formula properly. commit 7a0db25416639e76234b239a854b510e2043a91b Author: Merlijn Wajer Date: Sun Jun 5 19:44:52 2011 +0200 Add L*a*b CTS (3). commit 2e1e786d0ece69dc3e42fb92106a71dce0faf975 Author: Merlijn Wajer Date: Thu Jun 16 15:11:17 2011 +0200 FindBitmapToleranceIn now works. commit 58ea6021cd0cee3bd54f8ce93713bedc9ff3feb4 Author: Merlijn Wajer Date: Thu Jun 16 14:26:20 2011 +0200 CTS work. CTS 2 is still broken for bitmaps. commit 91d952d33ab9b8ddcb76bed991a1ea0c5907e084 Author: Merlijn Wajer Date: Thu Jun 16 12:52:10 2011 +0200 CTS cleanups. commit d9836a251c3ed4a3367383b7e182c648905fabee Merge: 5bf7d8b bfc3f86 Author: Merlijn Wajer Date: Mon Jun 13 20:44:08 2011 +0200 Merge branch 'master' into cts-rework commit 5bf7d8beeaf69133b03a3f8c04124f33dea4e24c Author: Merlijn Wajer Date: Mon Jun 13 20:38:00 2011 +0200 Completed first CTS rework. commit 7a412d16704f270ba44674c8422e1272c8994b11 Author: Merlijn Wajer Date: Mon Jun 13 20:21:23 2011 +0200 CTS: Cleanups. commit 14474a84ab69e15a1de3998dc01cb3053daba384 Author: Merlijn Wajer Date: Mon Jun 13 18:16:59 2011 +0200 CTS rework for FindColorsTolerance. commit b87a123701fb192b2f31efb8896d7e661b399c32 Author: Merlijn Wajer Date: Mon Jun 13 17:44:04 2011 +0200 More cleanups to CTS. commit 9415d0810088c37e7f0f79e2a31c7e723bd6152c Author: Merlijn Wajer Date: Mon Jun 13 17:41:06 2011 +0200 Finder: Trying a different CTS approach. --- Doc/sphinx/libmml/intro.rst | 3 + TODO | 5 +- Tests/PS/BmpBenchmark.simba | 25 ++ Tests/PS/bmpbench.simba | 12 +- Units/MMLCore/bitmaps.pas | 20 +- Units/MMLCore/colour_conv.pas | 52 ++- Units/MMLCore/finder.pas | 795 ++++++++++++++++++++-------------- Units/MMLCore/mufasatypes.pas | 8 + 8 files changed, 577 insertions(+), 343 deletions(-) create mode 100644 Tests/PS/BmpBenchmark.simba diff --git a/Doc/sphinx/libmml/intro.rst b/Doc/sphinx/libmml/intro.rst index 2a8d5a7..2828323 100644 --- a/Doc/sphinx/libmml/intro.rst +++ b/Doc/sphinx/libmml/intro.rst @@ -59,6 +59,8 @@ write - again - their own wrapper around libMML. This is what is being done with *pyMML*, the python libMML wrapper. It is still as much in development as libMML is, but the functionality exposed by libMML is succesfully used. +<<<<<<< HEAD +======= As of writing the pyMML usage looks like this, the passing around of a client may be removed in a later stage, or at least have it's behaviour changed. @@ -98,3 +100,4 @@ may be removed in a later stage, or at least have it's behaviour changed. print m.getPos() del DLL +>>>>>>> master diff --git a/TODO b/TODO index ba1abf6..9451910 100644 --- a/TODO +++ b/TODO @@ -7,13 +7,16 @@ Simple stuff, not required, may not be possible/useful: - CTS/finder speedups and changes [ ] - General ideas: + - Table displaying all the different performance gains and + penalties. [ ] + - General ideas: - everything subprocedure (lots of code) - jit + comparison function (per cts) generated, call in loop - comparison function (per cts), not generated, call in loop + - Investigate SIMD probable speedups [ ] - JIT (Generate comparison functions) [ ] - Comparison functions for HSL/XYZ/L*a*b should check for match on each component before calculating the next. diff --git a/Tests/PS/BmpBenchmark.simba b/Tests/PS/BmpBenchmark.simba new file mode 100644 index 0000000..5bf5551 --- /dev/null +++ b/Tests/PS/BmpBenchmark.simba @@ -0,0 +1,25 @@ +program new; +//http://farm4.static.flickr.com/3067/2612399892_7df428d482.jpg +{Make the above bitmap your target} +var + Bmp : integer; + x,y : integer; + w,h : integer; + t, i: integer; +begin + Bmp := createBitmap(15, 10); + FastDrawClear(bmp, clwhite); + GetClientDimensions(w,h); + + setcolortolerancespeed(2); + t:=getsystemtime; + for i := 0 to 10 do + FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,500); + writeln((getsystemtime-t) / 10.0); + + if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,500) then + begin + writeln('found'); + MoveMouse(x,y); + end; +end. diff --git a/Tests/PS/bmpbench.simba b/Tests/PS/bmpbench.simba index dc9acea..134b738 100644 --- a/Tests/PS/bmpbench.simba +++ b/Tests/PS/bmpbench.simba @@ -1,6 +1,5 @@ program new; -//http://farm4.static.flickr.com/3067/2612399892_7df428d482.jpg -{Make the above bitmap your target} + var Bmp : integer; x,y : integer; @@ -19,11 +18,14 @@ begin setcolortolerancespeed(c); t:=getsystemtime; - for i := 0 to 100 do + for i := 0 to 10 do findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,10); - writeln((getsystemtime-t) / 100.0); - if findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,200) then + writeln((getsystemtime-t) / 10.0); + if findBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,10) then + begin writeln('found'); + movemouse(x,y); + end; end; {if FindBitmapToleranceIn(bmp,x,y,0,0,w-1,h-1,300) then diff --git a/Units/MMLCore/bitmaps.pas b/Units/MMLCore/bitmaps.pas index 335550f..80ad422 100644 --- a/Units/MMLCore/bitmaps.pas +++ b/Units/MMLCore/bitmaps.pas @@ -64,6 +64,7 @@ type function FastGetPixel(x,y : integer) : TColor; function FastGetPixels(Points : TPointArray) : TIntegerArray; function GetAreaColors(xs,ys,xe,ye : integer) : T2DIntArray; + function GetHSLValues(xs, ys, xe, ye: integer): T2DHSLArray; procedure FastDrawClear(Color : TColor); procedure FastDrawTransparent(x, y: Integer; TargetBitmap: TMufasaBitmap); procedure FastReplaceColor(OldColor, NewColor: TColor); @@ -876,6 +877,23 @@ begin result[x-xs][y-ys] := BGRToRGB(FData[y*w+x]); end; +function TMufasaBitmap.GetHSLValues(xs, ys, xe, ye: integer): T2DHSLArray; +var + x, y: integer; + R, G, B, C: integer; +begin + ValidatePoint(xs,ys); + ValidatePoint(xe,ye); + setlength(result,ye-ys+1,xe-xs+1); + for y := ys to ye do + for x := xs to xe do + begin { REWRITE THIS } + RGBToHSL(FData[y*w+x].R, FData[y*w+x].G, FData[y*w+x].B, + Result[y-ys][x-xs].H, Result[y-ys][x-xs].S, + Result[y-ys][x-xs].L); + end; +end; + procedure TMufasaBitmap.SetTransparentColor(Col: TColor); begin self.FTransparentSet:= True; @@ -1406,7 +1424,7 @@ var i,minw,minh : integer; begin if (AWidth <> w) or (AHeight <> h) then - begin; + begin if AWidth*AHeight <> 0 then begin; NewData := GetMem(AWidth * AHeight * SizeOf(TRGB32)); diff --git a/Units/MMLCore/colour_conv.pas b/Units/MMLCore/colour_conv.pas index 2cbb3e3..de280b7 100644 --- a/Units/MMLCore/colour_conv.pas +++ b/Units/MMLCore/colour_conv.pas @@ -48,7 +48,8 @@ procedure ColorToXYZ(color: Integer; out X, Y, Z: Extended); inline; function XYZToColor(X, Y, Z: Extended): TColor; inline; function HSLToColor(H, S, L: Extended): TColor; inline; function BGRToRGB(BGR : TRGB32) : TColor;inline; - +procedure XYZtoCIELab(X, Y, Z: Extended; out L, a, b: Extended); +procedure CIELabtoXYZ(L, a, b: Extended; out X, Y, Z: Extended); implementation @@ -336,4 +337,53 @@ begin Result := RGBToColor(r, g, b); end; +procedure XYZtoCIELab(X, Y, Z: Extended; out L, a, b: Extended); +begin + X := X / 95.047; + Y := Y / 100.000; + Z := Z / 108.883; + + if ( X > 0.008856 ) then + X := Power(X, 1.0/3.0) + else + X := ( 7.787 * X ) + ( 16.0 / 116.0 ); + if ( Y > 0.008856 ) then + Y := Power(Y, 1.0/3.0) + else + Y := ( 7.787 * Y ) + ( 16.0 / 116.0 ); + if ( Z > 0.008856 ) then + Z := Power(Z, 1.0/3.0) + else + Z := ( 7.787 * Z ) + ( 16.0 / 116.0 ); + + L := (116.0 * Y ) - 16.0; + a := 500.0 * ( X - Y ); + b := 200.0 * ( Y - Z ); +end; + +procedure CIELabtoXYZ(L, a, b: Extended; out X, Y, Z: Extended); +begin + Y := ( L + 16 ) / 116.0; + X := ( a / 500.0 )+ Y; + Z := Y - ( b / 200.0 ); + + if ( Power(Y, 3) > 0.008856 ) then + Y := Power(Y, 3) + else + Y := ( Y - (16.0 / 116.0 )) / 7.787; + if ( Power(X, 3) > 0.008856 ) then + X := Power(X, 3) + else + X := ( X - (16.0 / 116.0) ) / 7.787; + if ( Power(Z, 3) > 0.008856 ) then + Z := Power(Z, 3) + else + Z := ( Z - (16.0 / 116.0) ) / 7.787; + + + X := 95.047 * X; + Y := 100.000 * Y; + Z := 108.883 * Z; +end; + end. diff --git a/Units/MMLCore/finder.pas b/Units/MMLCore/finder.pas index bb97efe..432dd89 100644 --- a/Units/MMLCore/finder.pas +++ b/Units/MMLCore/finder.pas @@ -30,15 +30,16 @@ interface {$define CheckAllBackground}//Undefine this to only check the first white point against the background (in masks). uses - colour_conv, Classes, SysUtils,bitmaps,MufasaBase,DTM, MufasaTypes; // Types + colour_conv, Classes, SysUtils, bitmaps, DTM, MufasaTypes; // Types { TMFinder Class } { - Should be 100% OS independant, - as all OS dependant code is in the IO Manager - + Should be 100% OS independant, as all OS dependant code is in the IO Manager. Let's try not to use any OS-specific defines here? ;) + + TODO: Check that each procedure calling Create_CTSInfo also calls + Free_CTSInfo(). } type @@ -68,7 +69,7 @@ type function FindColorSpiralTolerance(var x, y: Integer; color, xs, ys, xe, ye,Tol: Integer): Boolean; function FindColorTolerance(out x, y: Integer; Color, xs, ys, xe, ye, tol: Integer): Boolean; function FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; - function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer) : boolean; + function FindColorsSpiralTolerance(x, y: Integer; out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tol: Integer) : boolean; function FindColors(var TPA: TPointArray; Color, xs, ys, xe, ye: Integer): Boolean; function FindColoredArea(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea: Integer): Boolean; function FindColoredAreaTolerance(var x, y: Integer; color, xs, ys, xe, ye: Integer; MinArea, tol: Integer): Boolean; @@ -101,19 +102,42 @@ type implementation uses -// colour_conv,// For RGBToColor, etc. - Client, // For the Client Casts. - math, //min/max - mmath, - tpa, //TPABounds - dtmutil - ; + Client, // For the Client casting. + math, // min/max + tpa, //TPABounds + dtmutil; + +type + TCTS0Info = record + B, G, R, A: byte; + Tol: Integer; + end; + PCTS0Info = ^TCTS0Info; + + TCTS1Info = record + B, G, R, A: byte; + Tol: Integer; { Squared } + end; + PCTS1Info = ^TCTS1Info; + + TCTS2Info = record + H, S, L: extended; + hueMod, satMod: extended; + Tol: Integer; + end; + PCTS2Info = ^TCTS2Info; + + TCTSInfo = Pointer; + TCTSInfoArray = Array of TCTSInfo; + TCTSInfo2DArray = Array of TCTSInfoArray; + TCTSCompareFunction = function (ctsInfo: Pointer; C2: PRGB32): boolean; + procedure TMFinder.LoadSpiralPath(startX, startY, x1, y1, x2, y2: Integer); var i,c,Ring : integer; CurrBox : TBox; -begin; +begin i := 0; Ring := 1; c := 0; @@ -124,58 +148,60 @@ begin; if (startx >= x1) and (startx <= x2) and (starty >= y1) and (starty <= y2) then begin; ClientTPA[c] := Point(Startx, StartY); - inc(c); + Inc(c); end; - Repeat + repeat if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y1 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.x1 + 1 to CurrBox.x2 do if (I >= x1) and ( I <= x2) then begin; ClientTPA[c] := Point(i,CurrBox.y1); - inc(c); + Inc(c); end; if (CurrBox.x2 >= x1) and (CurrBox.x2 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.y1 + 1 to CurrBox.y2 do if (I >= y1) and ( I <= y2) then begin; ClientTPA[c] := Point(Currbox.x2, I); - inc(c); + Inc(c); end; if (CurrBox.x2 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y2 <= y2) then for i := CurrBox.x2 - 1 downto CurrBox.x1 do if (I >= x1) and ( I <= x2) then begin; ClientTPA[c] := Point(i,CurrBox.y2); - inc(c); + Inc(c); end; if (CurrBox.x1 >= x1) and (CurrBox.x1 <= x2) and (Currbox.y2 >= y1) and (Currbox.y1 <= y2) then for i := CurrBox.y2 - 1 downto CurrBox.y1 do if (I >= y1) and ( I <= y2) then begin; ClientTPA[c] := Point(Currbox.x1, I); - inc(c); + Inc(c); end; - inc(ring); + Inc(ring); CurrBox.x1 := Startx-ring; CurrBox.y1 := Starty-Ring; CurrBox.x2 := Startx+Ring; CurrBox.y2 := Starty+Ring; - until (Currbox.x1 < x1) and (Currbox.x2 > x2) and (currbox.y1 < y1) and (currbox.y2 > y2); + until (Currbox.x1 < x1) and (Currbox.x2 > x2) and (currbox.y1 < y1) + and (currbox.y2 > y2); end; -function CalculateRowPtrs(ReturnData : TRetData; RowCount : integer) : TPRGB32Array;overload; +function CalculateRowPtrs(ReturnData: TRetData; RowCount: integer) : TPRGB32Array; overload; var I : integer; begin; - setlength(result,RowCount); + SetLength(result,RowCount); for i := 0 to RowCount - 1 do result[i] := ReturnData.Ptr + ReturnData.RowLen * i; end; -function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array;overload; +function CalculateRowPtrs(Bitmap : TMufasaBitmap) : TPRGB32Array; overload; begin Result := Bitmap.RowPtrs; end; + //SkipCoords[y][x] = False/True; True means its "transparent" and therefore not needed to be checked. procedure CalculateBitmapSkipCoords(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray); var @@ -200,7 +226,9 @@ begin; inc(ptr); end; end; -//Points left holds the amount of points that are "left" to be checked (Including the point itself.. So for example Pointsleft[0][0] would hold the total amount of pixels that are to be checked. +{ Points left holds the amount of points that are "left" to be checked + (Including the point itself.. So for example Pointsleft[0][0] would + hold the total amount of pixels that are to be checked. } procedure CalculateBitmapSkipCoordsEx(Bitmap : TMufasaBitmap; out SkipCoords : T2DBoolArray;out TotalPoints : integer; out PointsLeft : T2DIntArray); var x,y : integer; @@ -239,6 +267,7 @@ begin; end; end; +{ Initialise the variables for TMFinder } constructor TMFinder.Create(aClient: TObject); var I : integer; @@ -268,7 +297,7 @@ end; procedure TMFinder.SetToleranceSpeed(nCTS: Integer); begin - if (nCTS < 0) or (nCTS > 2) then + if (nCTS < 0) or (nCTS > 3) then raise Exception.CreateFmt('The given CTS ([%d]) is invalid.',[nCTS]); Self.CTS := nCTS; end; @@ -294,6 +323,7 @@ function TMFinder.SimilarColors(Color1, Color2,Tolerance: Integer) : boolean; var R1,G1,B1,R2,G2,B2 : Byte; H1,S1,L1,H2,S2,L2 : extended; + L_1, a_1, b_1, L_2, a_2 ,b_2, X, Y, Z: extended; begin Result := False; ColorToRGB(Color1,R1,G1,B1); @@ -309,13 +339,27 @@ begin RGBToHSL(R2,g2,b2,H2,S2,L2); Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance)); end; + 3: + begin + RGBToXYZ(R1, G1, B1, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_1, a_1, b_1); + RGBToXYZ(R2, G2, B2, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); + Result := (abs(L_1 - L_2) < Tolerance) + and (abs(a_1 - a_2) < Tolerance) + and (abs(b_1 - b_2) < Tolerance); + end; end; end; +{ + TODO: Remove this +} function ColorSame(var CTS,Tolerance : Integer; var R1,G1,B1,R2,G2,B2 : byte; var H1,S1,L1,huemod,satmod : extended) : boolean; inline; var H2,S2,L2 : extended; + L_1, a_1, b_1, L_2, a_2 ,b_2, X, Y, Z: extended; begin Result := False; case CTS of @@ -325,6 +369,170 @@ begin RGBToHSL(R2,g2,b2,H2,S2,L2); Result := ((abs(H1 - H2) <= (hueMod * Tolerance)) and (abs(S2-S1) <= (satMod * Tolerance)) and (abs(L1-L2) <= Tolerance)); end; + 3: begin + RGBToXYZ(R1, G1, B1, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_1, a_1, b_1); + RGBToXYZ(R2, G2, B2, X, Y, Z); + XYZtoCIELab(X, Y, Z, L_2, a_2, b_2); + Result := Sqrt(sqr(L_1 - L_2) + sqr(a_1 - a_2) + + sqr(b_1 - b_2)) <= Tolerance; + end; + end; +end; + + +{ Colour Same functions } +function ColorSame_cts0(ctsInfo: Pointer; C2: PRGB32): boolean; + +var + C1: TCTS0Info; +begin + C1 := PCTS0Info(ctsInfo)^; + Result := (Abs(C1.B - C2^.B) <= C1.Tol) + and (Abs(C1.G - C2^.G) <= C1.Tol) + and (Abs(C1.R - C2^.R) <= C1.Tol); +end; + +function ColorSame_cts1(ctsInfo: Pointer; C2: PRGB32): boolean; + +var + C1: TCTS1Info; + r,g,b: integer; +begin + C1 := PCTS1Info(ctsInfo)^; + b := C1.B - C2^.B; + g := C1.G - C2^.G; + r := C1.R - C2^.R; + Result := (b*b + g*g + r*r) <= C1.Tol; +end; + +function ColorSame_cts2(ctsInfo: Pointer; C2: PRGB32): boolean; + +var + h, s, l: extended; + i: TCTS2Info; +begin + i := PCTS2Info(ctsInfo)^; + RGBToHSL(C2^.R, C2^.G, C2^.B, h, s, l); // Inline this later. + + Result := (abs(h - i.H) <= (i.hueMod)) + and (abs(s - i.S) <= (i.satMod)) + and (abs(l - i.L) <= i.Tol); +end; + +{ } + +function Create_CTSInfo(cts: integer; Color, Tol: Integer; + hueMod, satMod: extended): Pointer; overload; +var + R, G, B: Integer; +begin + case cts of + 0: + begin + Result := AllocMem(SizeOf(TCTS0Info)); + ColorToRGB(Color, PCTS0Info(Result)^.R, PCTS0Info(Result)^.G, + PCTS0Info(Result)^.B); + PCTS0Info(Result)^.Tol := Tol; + end; + 1: + begin + Result := AllocMem(SizeOf(TCTS1Info)); + ColorToRGB(Color, PCTS1Info(Result)^.R, PCTS1Info(Result)^.G, + PCTS1Info(Result)^.B); + + PCTS1Info(Result)^.Tol := Tol * Tol; + end; + 2: + begin + Result := AllocMem(SizeOf(TCTS2Info)); + ColorToRGB(Color, R, G, B); + RGBToHSL(R, G, B, PCTS2Info(Result)^.H, PCTS2Info(Result)^.S, + PCTS2Info(Result)^.L); + PCTS2Info(Result)^.hueMod := Tol * hueMod; + PCTS2Info(Result)^.satMod := Tol * satMod; + PCTS2Info(Result)^.Tol := Tol; + end; + end; +end; + + +function Create_CTSInfo(cts: integer; R, G, B, Tol: Integer; + hueMod, satMod: extended): Pointer; overload; + +var Color: Integer; + +begin + Color := RGBToColor(R, G, B); + Result := Create_CTSInfo(cts, Color, Tol, hueMod, satMod); +end; + +procedure Free_CTSInfo(i: Pointer); +begin + if assigned(i) then + FreeMem(i) + else + raise Exception.Create('Free_CTSInfo: Invalid TCTSInfo passed'); +end; + +{ TODO: Not universal, mainly for DTM } +function Create_CTSInfoArray(cts: integer; color, tolerance: array of integer; + hueMod, satMod: extended): TCTSInfoArray; + +var + i: integer; +begin + if length(color) <> length(tolerance) then + raise Exception.Create('Create_CTSInfoArray: Length(Color) <>' + +' Length(Tolerance'); + SetLength(Result, Length(color)); + + for i := High(result) downto 0 do + result := Create_CTSInfo(cts, color[i], tolerance[i], hueMod, satMod); +end; + + +{ TODO: Not universal, mainly for Bitmap } +function Create_CTSInfo2DArray(cts, w, h: integer; data: TPRGB32Array; + Tolerance: Integer; hueMod, satMod: Extended): TCTSInfo2DArray; +var + x, y: integer; +begin + SetLength(Result,h+1,w+1); + + for y := 0 to h do + for x := 0 to w do + Result[y][x] := Create_CTSInfo(cts, + data[y][x].R, data[y][x].G, data[y][x].B, + Tolerance, hueMod, satMod); +end; + +procedure Free_CTSInfoArray(i: TCTSInfoArray); +var + c: integer; +begin + for c := high(i) downto 0 do + Free_CTSInfo(i[c]); + SetLength(i, 0); +end; + +procedure Free_CTSInfo2DArray(i: TCTSInfo2DArray); +var + x, y: integer; +begin + for y := high(i) downto 0 do + for x := high(i[y]) downto 0 do + Free_CTSInfo(i[y][x]); + SetLength(i, 0); +end; + +function Get_CTSCompare(cts: Integer): TCTSCompareFunction; + +begin + case cts of + 0: Result := @ColorSame_cts0; + 1: Result := @ColorSame_cts1; + 2: Result := @ColorSame_cts2; end; end; @@ -400,37 +608,37 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc: Integer; - clR, clG, clB : byte; dX, dY, xx, yy: Integer; - h,s,l,hmod,smod : extended; - Ccts : integer; + + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; begin Result := 0; DefaultOperations(xs, ys, xe, ye); + dX := xe - xs; dY := ye - ys; - ColorToRGB(Color, clR, clG, clB); + PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; - CCts := Self.CTS; result := 0; - if cts = 2 then - begin; - RGBToHSL(clR,clG,clB,h,s,l); - hmod := Self.hueMod; - smod := Self.satMod; - end; + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tolerance, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + for yy := ys to ye do begin; for xx := xs to xe do - begin; - if ColorSame(CCts,Tolerance,clR,clG,clB,Ptr^.r,Ptr^.g,Ptr^.b,H,S,L,hmod,smod) then + begin + if compare(ctsinfo, Ptr) then inc(result); Inc(Ptr); end; Inc(Ptr, PtrInc) end; + + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -570,9 +778,11 @@ var PtrData: TRetData; RowData : TPRGB32Array; dX, dY, clR, clG, clB,i,Hispiral: Integer; - H1, S1, L1, H2, S2, L2: Extended; - HueXTol, SatXTol: Extended; - label Hit; + +var + j: integer; + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; begin Result := false; @@ -584,8 +794,6 @@ begin dY := ye - ys; //next, convert the color to r,g,b ColorToRGB(Color, clR, clG, clB); - if Cts = 2 then - RGBToHSL(clR,clG,clB,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); //Load rowdata @@ -593,47 +801,34 @@ begin //Load the spiral path LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); HiSpiral := (dy+1) * (dx + 1) -1; - case CTS of - 0: - for i := 0 to HiSpiral do - if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tol) and - (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tol) and - (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tol)) then - goto Hit; - 1: + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + + i := -1; + for j := 0 to HiSpiral do + begin + if compare(ctsinfo, @RowData[ClientTPA[j].y][ClientTPA[j].x]) then begin - Tol := Sqr(Tol); - for i := 0 to HiSpiral do - if (sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B) + - sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + - sqr(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R)) <= Tol then - goto Hit; - end; - 2: - { Can be optimized a lot... RGBToHSL isn't really inline, } - begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for i := 0 to HiSpiral do - begin - RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, - RowData[ClientTPA[i].y][ClientTPA[i].x].G, - RowData[ClientTPA[i].y][ClientTPA[i].x].B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - goto Hit; - end; + i := j; + break; end; end; - Result := False; - TClient(Client).IOManager.FreeReturnData; - Exit; - Hit: + Free_CTSInfo(ctsinfo); + + if i = -1 then + begin + Result := False; + TClient(Client).IOManager.FreeReturnData; + Exit; + end else + begin Result := True; x := ClientTPA[i].x + xs; y := ClientTPA[i].y + ys; TClient(Client).IOManager.FreeReturnData; + end; end; function TMFinder.FindColoredArea(var x, y: Integer; Color, xs, ys, xe, ye, MinArea: Integer): Boolean; @@ -699,7 +894,6 @@ begin Ptr := Before; Break; end; - Inc(Ptr, PtrInc); end; end; Inc(Ptr); @@ -848,11 +1042,13 @@ var PtrData: TRetData; Ptr: PRGB32; PtrInc: Integer; - dX, dY, clR, clG, clB, xx, yy: Integer; - H1, S1, L1, H2, S2, L2: Extended; - HueXTol, SatXTol: Extended; + dX, dY: Integer; + xx, yy: integer; + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; label Hit; + begin Result := false; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) @@ -861,10 +1057,6 @@ begin // calculate delta x and y dX := xe - xs; dY := ye - ys; - //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); - if Cts = 2 then - RGBToHSL(clR,clG,clB,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -873,54 +1065,22 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; - case CTS of - 0: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - goto Hit; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); - 1: + for yy := ys to ye do + begin + for xx := xs to xe do begin - Tol := Sqr(Tol); - - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (sqr(clB - Ptr^.B) + sqr(clG - Ptr^.G) + sqr(clR-Ptr^.R)) <= Tol then - goto Hit; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; - - end; - 2: - { Can be optimized a lot... RGBToHSL isn't really inline, } - begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do - begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - goto Hit; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; + if compare(ctsinfo, Ptr) then + goto Hit; + inc(Ptr); end; + Inc(Ptr, PtrInc); end; + Result := False; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; Exit; @@ -928,6 +1088,7 @@ begin Result := True; x := xx; y := yy; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -940,8 +1101,13 @@ var clR, clG, clB : Byte; H1, S1, L1: Extended; NotFound : Boolean; + + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; + label Hit; + begin Result := false; // checks for valid xs,ys,xe,ye? (may involve GetDimensions) @@ -961,13 +1127,17 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; Count := 0; + + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + for yy := ys to ye do begin; for xx := xs to xe do begin; NotFound := False; // Colour comparison here. - if ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then + if compare(ctsinfo, Ptr) then begin Before := Ptr; for fy := yy to ye do @@ -975,7 +1145,7 @@ begin for fx := xx to xe do begin Inc(Ptr); - if not ColorSame(CTS, Tol, Ptr^.R, Ptr^.G, Ptr^.B, clR, clG, clB, H1, S1, L1, huemod, satmod) then + if compare(ctsinfo, Ptr) then begin NotFound := True; Break; @@ -999,6 +1169,7 @@ begin end; Result := False; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; Exit; @@ -1006,27 +1177,28 @@ begin Result := True; x := xx; y := yy; + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; function TMFinder.FindColorsTolerance(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; var - PtrData: TRetData; - Ptr: PRGB32; - PtrInc,C: Integer; - dX, dY, clR, clG, clB, xx, yy: Integer; - H1, S1, L1, H2, S2, L2, hueXTol, satXTol: Extended; + PtrData: TRetData; + Ptr: PRGB32; + PtrInc,C: Integer; + dX, dY: Integer; + + xx, yy: integer; + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; + begin Result := false; DefaultOperations(xs,ys,xe,ye); dX := xe - xs; dY := ye - ys; - //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); - if CTS = 2 then - ColorToHSL(color,H1,S1,L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); @@ -1035,65 +1207,33 @@ begin Ptr := PtrData.Ptr; PtrInc := PtrData.IncPtrWith; c := 0; - case CTS of - 0: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if ((abs(clB-Ptr^.B) <= Tol) and (abs(clG-Ptr^.G) <= Tol) and (Abs(clR-Ptr^.R) <= Tol)) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(Ptr); - end; - Inc(Ptr, PtrInc); - end; - 1: - for yy := ys to ye do - begin - for xx := xs to xe do - begin - if (Sqrt(sqr(clR-Ptr^.R) + sqr(clG - Ptr^.G) + sqr(clB - Ptr^.B)) <= Tol) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - inc(c); - end; - inc(ptr); - end; - Inc(Ptr, PtrInc); - end; + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); - 2: + for yy := ys to ye do + begin + for xx := xs to xe do begin - HueXTol := hueMod * Tol; - SatXTol := satMod * Tol; - for yy := ys to ye do + if compare(ctsinfo, Ptr) then begin - for xx := xs to xe do - begin - RGBToHSL(Ptr^.R,Ptr^.G,Ptr^.B,H2,S2,L2); - if ((abs(H1 - H2) <= HueXTol) and (abs(S1 - S2) <= SatXTol) and (abs(L1 - L2) <= Tol)) then - begin; - ClientTPA[c].x := xx; - ClientTPA[c].y := yy; - Inc(c); - end; - Inc(Ptr) - end; - Inc(Ptr, PtrInc); + ClientTPA[c].x := xx; + ClientTPA[c].y := yy; + inc(c); end; + inc(Ptr); end; + Inc(Ptr, PtrInc); end; + SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; + + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; + function TMFinder.FindColorsToleranceOptimised(out Points: TPointArray; Color, xs, ys, xe, ye, Tol: Integer): Boolean; var @@ -1225,14 +1365,17 @@ begin end; function TMFinder.FindColorsSpiralTolerance(x, y: Integer; - out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer + out Points: TPointArray; color, xs, ys, xe, ye: Integer; Tol: Integer ): boolean; var - PtrData: TRetData; - c : integer; - RowData : TPRGB32Array; - dX, dY, clR, clG, clB, i,SpiralHi: Integer; - H1, S1, L1, H2, S2, L2, HueXTol, SatXTol: Extended; + PtrData: TRetData; + c : integer; + RowData : TPRGB32Array; + dX, dY, SpiralHi, i: Integer; + + compare: TCTSCompareFunction; + ctsinfo: TCTSInfo; + begin Result := false; DefaultOperations(xs,ys,xe,ye); @@ -1240,64 +1383,34 @@ begin dX := xe - xs; dY := ye - ys; //next, convert the color to r,g,b - ColorToRGB(Color, clR, clG, clB); - ColorToHSL(Color, H1, S1, L1); PtrData := TClient(Client).IOManager.ReturnData(xs, ys, dX + 1, dY + 1); c := 0; + ctsinfo := Create_CTSInfo(Self.CTS, Color, Tol, hueMod, satMod); + compare := Get_CTSCompare(Self.CTS); + //Load rowdata RowData:= CalculateRowPtrs(ptrdata,dy+1); //Load the spiral path - LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); + LoadSpiralPath(x-xs,y-ys,0,0,dx,dy); { Fills ClientTPA with Spiral path } + SpiralHi := (dx + 1) * (dy + 1) - 1; - case CTS of - 0: - for i := 0 to SpiralHi do - if ((abs(clB-RowData[ClientTPA[i].y][ClientTPA[i].x].B) <= Tolerance) and - (abs(clG-RowData[ClientTPA[i].y][ClientTPA[i].x].G) <= Tolerance) and - (Abs(clR-RowData[ClientTPA[i].y][ClientTPA[i].x].R) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - - - 1: - for i := 0 to SpiralHi do - if (Sqrt(sqr(clR - RowData[ClientTPA[i].y][ClientTPA[i].x].R) + - sqr(clG - RowData[ClientTPA[i].y][ClientTPA[i].x].G) + - sqr(clB - RowData[ClientTPA[i].y][ClientTPA[i].x].B)) <= Tolerance) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - - 2: + for i := 0 to SpiralHi do + if compare(ctsinfo, @RowData[ClientTPA[i].y][ClientTPA[i].x]) then begin; - HueXTol := hueMod * Tolerance; - SatXTol := satMod * Tolerance; - for i := 0 to SpiralHi do - begin; - RGBToHSL(RowData[ClientTPA[i].y][ClientTPA[i].x].R, - RowData[ClientTPA[i].y][ClientTPA[i].x].G, - RowData[ClientTPA[i].y][ClientTPA[i].x].B, - H2,S2,L2); - if ((abs(H1 - H2) <= (HueXTol)) and (abs(S1 - S2) <= (satXTol)) and (abs(L1 - L2) <= Tolerance)) then - begin; - ClientTPA[c].x := ClientTPA[i].x + xs; - ClientTPA[c].y := ClientTPA[i].y + ys; - inc(c); - end; - end; + { We can re-use the ClientTPA to store results. } + ClientTPA[c].x := ClientTPA[i].x + xs; + ClientTPA[c].y := ClientTPA[i].y + ys; + inc(c); end; - end; + SetLength(Points, C); Move(ClientTPA[0], Points[0], C * SizeOf(TPoint)); Result := C > 0; + + Free_CTSInfo(ctsinfo); TClient(Client).IOManager.FreeReturnData; end; @@ -1512,11 +1625,13 @@ var xBmp,yBmp : integer; tmpY : integer; dX, dY, xx, yy: Integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; - { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } + { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } begin Result := false; @@ -1537,10 +1652,10 @@ begin //Heck our bitmap cannot be outside the search area dX := dX - bmpW; dY := dY - bmpH; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); @@ -1552,21 +1667,24 @@ begin tmpY := yBmp + yy; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + xx].R,MainRowdata[tmpY][xBmp + xx].G,MainRowdata[tmpY][xBmp + xx].B, - H,S,L,HMod,SMod) then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + xx]) then goto NotFoundBmp; - end; + //We did find the Bmp, otherwise we would be at the part below + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; + x := xx + xs; y := yy + ys; result := true; - exit; + Exit; NotFoundBmp: end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; @@ -1642,9 +1760,11 @@ var xBmp,yBmp : integer; tmpY : integer; dX, dY, i,HiSpiral: Integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1670,9 +1790,11 @@ begin //Load the spiral into memory LoadSpiralPath(x-xs,y-ys,0,0,dX,dY); HiSpiral := (dx+1) * (dy+1) - 1; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; + + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); @@ -1683,15 +1805,14 @@ begin tmpY := yBmp + ClientTPA[i].y; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].B, - H,S,L,HMod,SMod) then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + ClientTPA[i].x]) then goto NotFoundBmp; end; //We did find the Bmp, otherwise we would be at the part below + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; x := ClientTPA[i].x + xs; @@ -1700,6 +1821,7 @@ begin exit; NotFoundBmp: end; + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; @@ -1714,9 +1836,11 @@ var tmpY : integer; dX, dY, i,HiSpiral: Integer; FoundC : integer; - CCTS : integer; - H,S,L,HMod,SMod : extended; SkipCoords : T2DBoolArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label NotFoundBmp; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1742,10 +1866,12 @@ begin //Load the spiral into memory LoadSpiralPath(x-xs,y-ys,0,0,dX,dY); HiSpiral := (dx+1) * (dy+1) - 1; - //Compiler hints - HMod := 0;SMod := 0;H := 0.0;S := 0.0; L := 0.0; - CCTS := Self.CTS; FoundC := 0; + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + //Get the "skip coords". CalculateBitmapSkipCoords(Bitmap,SkipCoords); for i := 0 to HiSpiral do @@ -1755,11 +1881,8 @@ begin tmpY := yBmp + ClientTPA[i].y; for xBmp := 0 to BmpW do if not SkipCoords[yBmp][xBmp] then - if not ColorSame(CCTS,tolerance, - BmpRowData[yBmp][xBmp].R,BmpRowData[yBmp][xBmp].G,BmpRowData[yBmp][xBmp].B, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].R,MainRowdata[tmpY][xBmp + ClientTPA[i].x].G, - MainRowdata[tmpY][xBmp + ClientTPA[i].x].B, - H,S,L,HMod,SMod) then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[tmpY][xBmp + ClientTPA[i].x]) then goto NotFoundBmp; end; @@ -1775,6 +1898,8 @@ begin SetLength(Points,FoundC); Move(ClientTPA[0], Points[0], FoundC * SizeOf(TPoint)); end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; end; @@ -1797,6 +1922,10 @@ var TotalC : integer; SkipCoords : T2DBoolArray; PointsLeft : T2DIntArray; + + ctsinfoarray: TCTSInfo2DArray; + compare: TCTSCompareFunction; + label FoundBMPPoint, Madness; { Don't know if the compiler has any speed-troubles with goto jumping in nested for loops. } @@ -1824,6 +1953,11 @@ begin Accuracy := 0; BestCount := -1; BestPT := Point(-1,-1); + + ctsinfoarray := Create_CTSInfo2DArray(Self.CTS, bmpW, bmpH, BmpRowData, + Tolerance, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + //Get the "skip coords". and PointsLeft (so we can calc whether we should stop searching or not ;-). CalculateBitmapSkipCoordsEx(Bitmap,SkipCoords,TotalC,PointsLeft); @@ -1850,8 +1984,8 @@ begin xEnd := Min(xx+range + xBmp,SearchdX); for RangeX := xStart to xEnd do begin; - if Sqrt(sqr(BmpRowData[yBmp][xBmp].R - MainRowdata[RangeY][RangeX].R) + sqr(BmpRowData[yBmp][xBmp].G - MainRowdata[RangeY][RangeX].G) - +sqr(BmpRowData[yBmp][xBmp].B - MainRowdata[RangeY][RangeX].B)) <= tolerance then + if not compare(ctsinfoarray[yBmp][xBmp], + @MainRowData[rangeY][rangeX]) then goto FoundBMPPoint; end; end; @@ -1869,7 +2003,8 @@ begin BestCount := GoodCount; BestPT := Point(xx+xs,yy+ys); if GoodCount = TotalC then - begin; + begin + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; x := BestPT.x; y := BestPT.y; @@ -1878,6 +2013,8 @@ begin end; end; end; + + Free_CTSInfo2DArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; if BestCount = 0 then Exit; @@ -1912,16 +2049,9 @@ end; //MaxToFind, if it's < 1 it won't stop looking function TMFinder.FindDTMs(DTM: TMDTM; out Points: TPointArray; x1, y1, x2, y2, maxToFind: Integer): Boolean; var - //Cache DTM stuff - Len : integer; //Len of the points - DPoints : PMDTMPoint; //DTM Points - // Colours of DTMs - clR,clG,clB : array of byte; - - //Similar colors stuff - hh,ss,ll: array of extended; - hmod,smod: extended; - Ccts : integer; + //Cache DTM stuff + Len : integer; //Len of the points + DPoints : PMDTMPoint; //DTM Points // Bitwise b: Array of Array of Integer; @@ -1949,11 +2079,13 @@ var goodPoints: Array of Boolean; + col_arr, tol_arr: Array of Integer; + ctsinfoarray: TCTSInfoArray; + compare: TCTSCompareFunction; + label theEnd; label AnotherLoopEnd; - - begin // Is the area valid? DefaultOperations(x1, y1, x2, y2); @@ -1984,26 +2116,22 @@ begin FillChar(b[i][0], SizeOf(Integer) * (H+1), 0); end; - // C = DTM.C - SetLength(clR,Len); - SetLength(clG,Len); - SetLength(clB,Len); - for i := 0 to Len - 1 do - ColorToRGB(DPoints[i].c,clR[i],clG[i],clB[i]); - - SetLength(hh,Len); - SetLength(ss,Len); - SetLength(ll,Len); - for i := 0 to Len - 1 do - ColorToHSL(DPoints[i].c,hh[i],ss[i],ll[i]); - - GetToleranceSpeed2Modifiers(hMod, sMod); - - ccts := CTS; - // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + SetLength(col_arr, Len); + SetLength(tol_arr, Len); + // C = DTM.C + for i := 0 to Len - 1 do + begin + col_arr[i] := DPoints[i].c; + tol_arr[i] := DPoints[i].t; + end; + + ctsinfoarray := Create_CTSInfoArray(Self.CTS, + col_arr, tol_arr, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + cd := CalculateRowPtrs(PtrData, h + 1); //CD starts at 0,0.. We must adjust the MA, since this is still based on the xs,ys,xe,ye box. MA.x1 := MA.x1 - x1; @@ -2037,7 +2165,7 @@ begin // Checking point i now. (Store that we matched it) ch[xxx][yyy]:= ch[xxx][yyy] or (1 shl i); // if SimilarColors(dtm.c[i], rgbtocolor(cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B), DPoints[i].t) then - if ColorSame(ccts,DPoints[i].t,clR[i],clG[i],clB[i],cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B,hh[i],ss[i],ll[i],hmod,smod) then + if compare(ctsinfoarray[i], @cd[yyy][xxx]) then b[xxx][yyy] := b[xxx][yyy] or (1 shl i); end; @@ -2066,6 +2194,8 @@ begin AnotherLoopEnd: end; TheEnd: + + Free_CTSInfoArray(ctsinfoarray); TClient(Client).IOManager.FreeReturnData; SetLength(Points, pc); @@ -2082,14 +2212,15 @@ var begin FindDTMsRotated(dtm, P, x1, y1, x2, y2, sAngle, eAngle, aStep, F,Alternating,1); if Length(P) = 0 then - exit(false); + exit(False); aFound := F[0][0]; x := P[0].x; y := P[0].y; Exit(True); end; -procedure RotPoints_DTM(const P: TPointArray;var RotTPA : TPointArray; const A: Extended); +procedure RotPoints_DTM(const P: TPointArray;var RotTPA : TPointArray; const A: + Extended); inline; var I, L: Integer; begin @@ -2103,18 +2234,11 @@ end; function TMFinder.FindDTMsRotated(DTM: TMDTM; out Points: TPointArray; x1, y1, x2, y2: Integer; sAngle, eAngle, aStep: Extended; out aFound: T2DExtendedArray;Alternating : boolean; maxToFind: Integer): Boolean; var - //Cached variables - Len : integer; - DPoints : PMDTMPoint; - DTPA : TPointArray; - RotTPA: TPointArray; - // Colours of DTMs - clR,clG,clB : array of byte; - - //Similar colors stuff - hh,ss,ll: array of extended; - hmod,smod: extended; - Ccts : integer; + //Cached variables + Len : integer; + DPoints : PMDTMPoint; + DTPA : TPointArray; + RotTPA: TPointArray; // Bitwise b: Array of Array of Integer; @@ -2144,11 +2268,14 @@ var // point count pc: Integer = 0; - ac: Integer = 0; goodPoints: Array of Boolean; s: extended; + col_arr, tol_arr: Array of Integer; + ctsinfoarray: TCTSInfoArray; + compare: TCTSCompareFunction; + label theEnd; label AnotherLoopEnd; @@ -2184,20 +2311,6 @@ begin FillChar(ch[i][0], SizeOf(Integer) * (H+1), 0); end; - // Convert colors to there components - SetLength(clR,Len); - SetLength(clG,Len); - SetLength(clB,Len); - for i := 0 to Len - 1 do - ColorToRGB(DPoints[i].c,clR[i],clG[i],clB[i]); - //Compiler hints - - SetLength(hh,Len); - SetLength(ss,Len); - SetLength(ll,Len); - for i := 0 to Len - 1 do - ColorToHSL(DPoints[i].c,hh[i],ss[i],ll[i]); - { When we search for a rotated DTM, everything is the same, except the coordinates.. Therefore we create a TPA of the 'original' DTM, containing all the Points. @@ -2207,12 +2320,22 @@ begin for i := 0 to len-1 do DTPA[i] := Point(DPoints[i].x,DPoints[i].y); - GetToleranceSpeed2Modifiers(hMod, sMod); - ccts := CTS; - // Retreive Client Data. PtrData := TClient(Client).IOManager.ReturnData(x1, y1, W + 1, H + 1); + SetLength(col_arr, Len); + SetLength(tol_arr, Len); + // C = DTM.C + for i := 0 to Len - 1 do + begin + col_arr[i] := DPoints[i].c; + tol_arr[i] := DPoints[i].t; + end; + + ctsinfoarray := Create_CTSInfoArray(Self.CTS, + col_arr, tol_arr, self.hueMod, self.satMod); + compare := Get_CTSCompare(Self.CTS); + cd := CalculateRowPtrs(PtrData, h + 1); SetLength(aFound, 0); SetLength(Points, 0); @@ -2258,7 +2381,7 @@ begin // Checking point i now. (Store that we matched it) ch[xxx][yyy]:= ch[xxx][yyy] or (1 shl i); - if ColorSame(ccts,DPoints[i].t,clR[i],clG[i],clB[i],cd[yyy][xxx].R, cd[yyy][xxx].G, cd[yyy][xxx].B,hh[i],ss[i],ll[i],hmod,smod) then + if compare(ctsinfoarray[i], @cd[yyy][xxx]) then b[xxx][yyy] := b[xxx][yyy] or (1 shl i); end; @@ -2290,7 +2413,6 @@ begin goto theEnd; AnotherLoopEnd: end; - ac := 0; if Alternating then begin if AngleSteps mod 2 = 0 then //This means it's an even number, thus we must add a positive step @@ -2302,7 +2424,10 @@ begin s := s + aStep; end; TheEnd: - TClient(Client).IOManager.FreeReturnData; + + Free_CTSInfoArray(ctsinfoarray); + TClient(Client).IOManager.FreeReturnData; + Result := (pc > 0); { Don't forget to pre calculate the rotated points at the start. Saves a lot of rotatepoint() calls. } diff --git a/Units/MMLCore/mufasatypes.pas b/Units/MMLCore/mufasatypes.pas index ef1adea..a5e4cf2 100644 --- a/Units/MMLCore/mufasatypes.pas +++ b/Units/MMLCore/mufasatypes.pas @@ -60,6 +60,14 @@ type TRGB32Array = array of TRGB32; TPRGB32Array = array of PRGB32; //Array of Pointers + THSL = record + H, S, L: extended; + end; + PHSL = ^THSL; + + THSLArray = array of THSL; + T2DHSLArray = array of array of THSL; + TRetData = record Ptr : PRGB32; IncPtrWith : integer;