marpis
2010-12-12 04:30:30
Here comes the source (only the .dll) to the first real color worldwalker, Galileo. :)
Lazarus compiles it, but when I run the script below, It says
Lazarus compiles it, but when I run the script below, It says
Exception in Script: Error loading plugin C:\Simba\Plugins\project1.dll
library Galileo;
{$mode objfpc}{$H+}
uses
Classes, sysutils, Windows, Crt;
//{$IFDEF WINDOWS}{$R project1.rc}{$ENDIF}
type
TColorBox = record
width, height: integer;
tol: extended;
Red, Green, Blue: extended;
end;
TMap = record
Boxes: Array of Array of TColorBox; // Boxes[x][y]
BoxWidth, BoxHeight: integer;
end;
procedure ColorToRGB(Color: Integer; var r, g, b: Integer);
begin
r := (Color) and 255;
g := (Color shr 8) and 255;
b := (Color shr 16) and 255;
end;
function MakeColorBoxEx(bmp, x1, y1, x2, y2: integer): TColorBox; register;
var
x, y: integer;
R, G, B: integer;
begin
Result.width := x2 - x1;
Result.height := y2 - y1;
for x := x1 to x2 do
for y := y1 to y2 do
begin
try
ColorToRGB(GetPixel(bmp, x, y), R, G, B);
with Result do
begin
Red := Red + R;
Green := Green + G;
Blue := Blue + B;
end;
except
writeln('ColorToRGB exception: '+inttostr(x)+', '+inttostr(y));
end;
end;
end;
function ColorBoxesMatch(B1, B2: TColorBox; tol: extended): boolean;
begin
if (B1.Red >= (B2.Red*(1-tol))) and (B1.Red <= (B2.Red*(1+tol))) then
if (B1.Green >= (B2.Green*(1-tol))) and (B1.Green <= (B2.Green*(1+tol))) then
if (B1.Blue >= (B2.Blue*(1-tol))) and (B1.Blue <= (B2.Blue*(1+tol))) then
begin
Result := True;
Exit;
end;
end;
function FindMapInMapExx(LargeMap, SmallMap: TMap; tol: extended; MaxFails: integer): TPoint; register;
var
x, y, HighX, HighY: integer;
xx, yy: integer;
Matching: integer;
begin
Result.X := -1;
Result.Y := -1;
HighX := High(LargeMap.Boxes);
HighY := High(LargeMap.Boxes[0]);
writeln('HighX = '+inttostr(HighX)+', HighY = '+inttostr(HighY));
for x := 0 to HighX do
for y := 0 to HighY do
if ColorBoxesMatch(LargeMap.Boxes[x][y], SmallMap.Boxes[0][0], tol) then
begin
Matching := 0;
try
// top left matches, let's compare the others
for xx := 0 to 15 do
for yy := 0 to 15 do
if ColorBoxesMatch(LargeMap.Boxes[x+xx][y+yy], SmallMap.Boxes[xx][yy], tol) then
Inc(Matching);
//writeln('matching: '+inttostr(matching));
if Matching >= (256 - MaxFails) then // 16*16 = 256
begin
Result.X := (x + 8)*LargeMap.BoxWidth; // +8 cause we want the center
Result.Y := (y + 8)*LargeMap.BoxHeight;
Exit;
end;
except
end;
end;
end;
function FindMapInMapLoop(SmallMap, LargeMap: TMap; mintol, maxtol, tolstep: extended; minfails, maxfails, failsstep: integer): TPoint; register;
var
i, ii, fails: integer;
tol: extended;
begin
tol := mintol;
while (tol < maxtol) do
begin
fails := minfails;
while (fails < maxfails) do
begin
Result := FindMapInMapExx(LargeMap, SmallMap, tol, fails);
if (Result.X > 0) and (Result.Y > 0) then
Exit;
fails := fails + failsstep;
end;
tol := tol + tolstep;
end;
end;
function BitmapToTMap(path: string; bmpWidth, bmpHeight, boxwidth, boxheight: integer): TMap; register;
var
bmp: integer;
X, Y, HighX, HighY: integer;
begin
bmp := LoadImage(0, PChar(path), IMAGE_BITMAP, bmpWidth, bmpHeight, LR_LOADFROMFILE);
Result.BoxHeight := boxheight;
Result.BoxWidth := boxwidth;
HighX := Trunc(bmpWidth / (boxwidth*1.0));
HighY := Trunc(bmpHeight / (boxheight*1.0));
for X := 0 to HighX-1 do
begin
SetLength(Result.Boxes, HighX);
for Y := 0 to HighY-1 do
begin
SetLength(Result.Boxes[X], HighY);
Result.Boxes[X][Y] := MakeColorBoxEx(bmp, X*boxwidth, Y*boxheight, (X+1)*boxwidth, (Y+1)*boxheight);
end;
end;
end;
//////
function GetFunctionCount(): Integer; stdcall; export;
begin
Result := 4;
end;
function GetFunctionCallingConv(x : Integer) : Integer; stdcall; export;
begin
Result := 0;
case x of
0..3 : Result := 1;
end;
end;
function GetFunctionInfo(x: Integer; var ProcAddr: Pointer; var ProcDef: PChar): Integer; stdcall; export;
begin
case x of
0:
begin
ProcAddr := @MakeColorBoxEx;
StrPCopy(ProcDef, 'function MakeColorBoxEx(bmp, x1, y1, x2, y2: integer): TColorBox;');
end;
1:
begin
ProcAddr := @ColorBoxesMatch;
StrPCopy(ProcDef, 'function ColorBoxesMatch(B1, B2: TColorBox; tol: extended): boolean;');
end;
2:
begin
ProcAddr := @FindMapInMapExx;
StrPCopy(ProcDef, 'function FindMapInMapExx(LargeMap, SmallMap: TMap; tol: extended; MaxFails: integer): TPoint;');
end;
3:
begin
ProcAddr := @FindMapInMapLoop;
StrPCopy(ProcDef, 'function FindMapInMapLoop(SmallMap, LargeMap: TMap; mintol, maxtol, tolstep: extended; minfails, maxfails, failsstep: integer): TPoint;');
end;
else
x := -1;
end;
Result := x;
end;
exports GetFunctionCount;
exports GetFunctionInfo;
exports GetFunctionCallingConv;
begin
end.
program GalileoTest;
{.include SRL/SRL.scar}
{$LOADLIB project1.dll}
type
TColorBox = record
width, height: integer;
tol: extended;
Red, Green, Blue: extended;
end;
TMap = record
Boxes: Array of Array of TColorBox; // Boxes[x][y]
BoxWidth, BoxHeight: integer;
end;
var
B: TColorBox;
begin
B := MakeColorBoxEx(LoadBitmap(AppPath+'/Includes/SRL/SRL/worldmap.bmp'), 10, 10, 20, 20);
end.