SRL Archive - Help and Support

Problem with SetTargetBitmap


marpis

2011-11-25 12:44:15

I am trying to set SPS area bitmaps as targets so I could use FindBitmap to them. I keep getting this error:

Error: Exception: You passed wrong values to a finder function: xs > xe (0,-1). at line 43
and I thought I try to manually tell it the bitmap size by using FindBitmapIn(bmp, tmp, tmp, 0, 0, 499, 499); but then I get this:

Error: Exception: You passed a wrong xe to a finder function: 499. [B]The client has a width of 0[/B], thus the xe is out of bounds. at line 43
The bolded part is probably the key to the answer.

Here's my code:

program SPS_object_recognizer;
{.include srl/srl.scar}
{.include sps/sps.simba}

const
ImgPath = AppPath + '/Includes/sps/img/static_objects/';
TotalObjects = 7;
// ObjectTolerance = 10;

var
MapObjects: Array [0..(TotalObjects - 1)] of integer;
AreaObjectInfo: Array [0..17] of Array [0..13] of TBooleanArray;


procedure InitObjects;
var
i: integer;
begin
MapObjects[0] := LoadBitmap(ImgPath + 'deadtree.bmp');
MapObjects[1] := LoadBitmap(ImgPath + 'palmtree.bmp');
MapObjects[2] := LoadBitmap(ImgPath + 'rock1.bmp');
MapObjects[3] := LoadBitmap(ImgPath + 'rock2.bmp');
MapObjects[4] := LoadBitmap(ImgPath + 'tree1.bmp');
MapObjects[5] := LoadBitmap(ImgPath + 'tree2.bmp');
MapObjects[6] := LoadBitmap(ImgPath + 'tree3.bmp');

for i := high(MapObjects) downto 0 do
SetTransparentColor(MapObjects[i], clRed);
end;

procedure GetObjectsInArea(areaX, areaY: integer);
var
TBA: TBooleanArray;
bmp, i, tmp: integer;
s: string;
begin
SetLength(TBA, TotalObjects);
s := ToStr(areaX)+'_'+ToStr(areaY);
bmp := LoadBitmap(AppPath + '/Includes/sps/sps/img/runescape_surface/' + s + '.png');
bmp := SetTargetBitmap(bmp);

for i := (TotalObjects - 1) downto 0 do
if FindBitmap(MapObjects[i], tmp, tmp) then
TBA[i] := True
else
TBA[i] := False;

FreeBitmap(bmp);
writeln('SPS_AreaObjectInfo['+ToStr(areax)+']['+ToStr(areay)+'] := '+ToStr(TBA)+';');
end;

procedure CreateAllAreaObjectInfo;
var
x, y: integer;
s: string;
begin
InitObjects;

for x := 0 to 17 do
for y := 0 to 13 do
begin
s := ToStr(x)+'_'+ToStr(y);

if not FileExists(AppPath + '/Includes/sps/img/runescape_surface/' + s +'.png') then
Continue;

GetObjectsInArea(x, y);
end;
end;

function GetAllAreasWithObjects(ObjectsToFind: TBooleanArray): TStringArray;
var
x, y, i, L: integer;
b: boolean;
s: string;
begin
SetLength(Result, 999);

for x := 0 to 17 do
for y := 0 to 13 do
begin
s := ToStr(x)+'_'+ToStr(y);

if not FileExists(AppPath + '/Includes/sps/img/runescape_surface/' + s +'.png') then
Continue;

Writeln('Scanning area: '+s);
b := true;
for i := (TotalObjects - 1) downto 0 do
if (ObjectsToFind[i] = True) and (AreaObjectInfo[x][y][i] = False) then
begin
b := false;
Break;
end;

if b then
begin
Result[L] := s;
Inc(L);
end;
end;
end;


begin
CreateAllAreaObjectInfo;
end.

EDIT: Also as you can see, I'm trying to set clRed transparent in InitObjects and then use the regular FindBitmap. Feel free to tell me if that doesn't work! :p I'm quite sure it doesn't work, but I'm bored and want to try.

Wizzup?

2011-11-27 06:39:12

Hm.. this should work. Let me look at this.

This works for me:


program new;
var bmp, x, y:integer;
begin
bmp := LoadBitmap('2011-11-27-124117_1920x1080_scrot.png');
SetTargetBitmap(bmp);
GetBitmapSize(bmp, x, y);
writeln('x: ' + inttostr(x) + ', y: ' + inttostr(y));
GetClientDimensions(x,y);
writeln('x: ' + inttostr(x) + ', y: ' + inttostr(y));
if FindBitmap(bmp, x, y) then
writeln('found');
end.

Try calling GetBitmapSize on the bitmap you're loading. Perhaps the size is simply invalid?

marpis

2011-11-27 10:41:11

Weird.. It says the bitmap is 8x8 when the real size is 500x500. Could this be because I'm trying to load .png using LoadBitmap?
Also, GetClientDimensions returns 0x0.

EDIT: But you tried it with .png too… Hmm…
EDIT: Damn I'm stupid! I've had the bitmap location path all wrong! Problem solved… for now.

Wizzup?

2011-11-27 11:12:21

From: marpis
Weird.. It says the bitmap is 8x8 when the real size is 500x500. Could this be because I'm trying to load .png using LoadBitmap?
Also, GetClientDimensions returns 0x0.

EDIT: But you tried it with .png too… Hmm…
EDIT: Damn I'm stupid! I've had the bitmap location path all wrong! Problem solved… for now.


Perhaps FreeBitmap doesn't raise an exception on an invalid file.
I just tested, and it doesn't. I'll try to get this into Simba 0.98.

Also, even if it cannot load the bitmap, you'll still have to free it. I'll look into this as well.

marpis

2011-11-27 11:14:56

FFS! What now…


Error: Exception: The bitmap[1] does not exist at line 59

I'm trying to search 7 bitmaps over and over again in different areas and make a profile from that info, and it works just fine for the first time but when it goes to the second area it says that the bitmap[1] does not exist. This is very weird because the 6 first don't cause this problem.
I have the bitmaps in an Array [1..7] of Integer; and use for-downto when going through them. Bitmaps 7-2 don't cause errors, but when it reaches 1 it does.
I already tried indexing them 0..6, but that doesn't help. Same thing happens.

EDIT:
Ok now it's very weird. I added a try-except to keep it going anyway, and it seems to lose 1 bitmap per round!
The first one goes ok, then it doesn't find bitmap[1], after that it doesn't find bitmaps 1 or 2, and so on.

latest code:

program SPS_object_recognizer;
{.include srl/srl.scar}
{.include sps/sps.simba}

const
ImgPath = AppPath + '/Includes/sps/img/static_objects/';
TotalObjects = 7;
// ObjectTolerance = 10;

var
MapObjects: Array [1..TotalObjects] of integer;
AreaObjectInfo: Array [0..17] of Array [0..13] of TBooleanArray;


procedure LoadMapObjects;
var
i: integer;
begin
MapObjects[1] := LoadBitmap(ImgPath + 'deadtree.bmp');
MapObjects[2] := LoadBitmap(ImgPath + 'palmtree.bmp');
MapObjects[3] := LoadBitmap(ImgPath + 'rock1.bmp');
MapObjects[4] := LoadBitmap(ImgPath + 'rock2.bmp');
MapObjects[5] := LoadBitmap(ImgPath + 'tree1.bmp');
MapObjects[6] := LoadBitmap(ImgPath + 'tree2.bmp');
MapObjects[7] := LoadBitmap(ImgPath + 'tree3.bmp');

for i := high(MapObjects) downto 1 do
SetTransparentColor(MapObjects[i], clRed);

end;

procedure FreeMapObjects;
var
i: integer;
begin
for i := high(MapObjects) downto 1 do
FreeBitmap(MapObjects[i]);
end;

procedure GetObjectsInArea(areaX, areaY: integer);
var
TBA: Array [1..TotalObjects] of Boolean;
bmp, i, tmp, x, y: integer;
s: string;
begin
s := ToStr(areaX)+'_'+ToStr(areaY);
bmp := LoadBitmap(AppPath + '/Includes/sps/img/runescape_surface/' + s + '.png');
bmp := SetTargetBitmap(bmp);
{
GetBitmapSize(bmp, x, y);
Writeln(ToStr(x)+', '+ToStr(y));
GetClientDimensions(x, y);
Writeln(ToStr(x)+', '+ToStr(y));
}

for i := high(MapObjects) downto 1 do
begin
try
if FindBitmapToleranceIn(MapObjects[i], x, y, 0, 0, 499, 499, 25) then
TBA[i] := True
else
TBA[i] := False;
except
Writeln(ExceptionToString(ExceptionType, ExceptionParam));
end;
end;

FreeBitmap(bmp);
writeln('SPS_AreaObjectInfo['+ToStr(areax)+']['+ToStr(areay)+'] := '+ToStr(TBA)+';');
end;

procedure CreateAllAreaObjectInfo;
var
x, y: integer;
s: string;
begin
LoadMapObjects;

for x := 0 to 17 do
for y := 0 to 13 do
begin
s := ToStr(x)+'_'+ToStr(y);

if not FileExists(AppPath + '/Includes/sps/img/runescape_surface/' + s +'.png') then
Continue;

GetObjectsInArea(x, y);
end;

FreeMapObjects;
end;

function GetAllAreasWithObjects(ObjectsToFind: TBooleanArray): TStringArray;
var
x, y, i, L: integer;
b: boolean;
s: string;
begin
SetLength(Result, 999);

for x := 0 to 17 do
for y := 0 to 13 do
begin
s := ToStr(x)+'_'+ToStr(y);

if not FileExists(AppPath + '/Includes/sps/img/runescape_surface/' + s +'.png') then
Continue;

Writeln('Scanning area: '+s);
b := true;
for i := TotalObjects downto 1 do
if (ObjectsToFind[i] = True) and (AreaObjectInfo[x][y][i] = False) then
begin
b := false;
Break;
end;

if b then
begin
Result[L] := s;
Inc(L);
end;
end;

SetLength(Result, L);
end;

begin
CreateAllAreaObjectInfo;
end.


Wizzup?

2011-11-27 11:36:41

I've fixed LoadBitmap to throw an exception if it cannot load the bitmap - but before returning the script it will free the bitmap, so that should be fine. I'm not sure about your current issue but I'm not sure if that is directly a Simba problem.


E: If the bitmap loading still silently fails (with your current simba, it won't with the newer one), you may be freeing a different/wrong bitmap.

marpis

2011-11-30 02:13:37

To me it somehow looks like FindBitmapToleranceIn would free the bitmap? Not the target bitmap, but the one we are looking for.

In this loop, somehow bitmaps in the array MapObjects[] get free'd or destroyed.

procedure GetObjectsInArea(areaX, areaY: integer);
var
TBA: Array [1..TotalObjects] of Boolean;
bmp, tmpbmp, i, tmp, x, y: integer;
s: string;
begin
s := ToStr(areaX)+'_'+ToStr(areaY);
bmp := LoadBitmap(AppPath + '/Includes/sps/img/runescape_surface/' + s + '.png');
bmp := SetTargetBitmap(bmp);
{
GetBitmapSize(bmp, x, y);
Writeln(ToStr(x)+', '+ToStr(y));
GetClientDimensions(x, y);
Writeln(ToStr(x)+', '+ToStr(y));
}

for i := high(MapObjects) downto 1 do
begin
try
if FindBitmapToleranceIn(MapObjects[i], x, y, 0, 0, 499, 499, 25) then
TBA[i] := True
else
TBA[i] := False;
except
Writeln(ExceptionToString(ExceptionType, ExceptionParam));
end;
end;

FreeBitmap(bmp);
writeln('SPS_AreaObjectInfo['+ToStr(areax)+']['+ToStr(areay)+'] := '+ToStr(TBA)+';');
end;

EDIT: Ok, somehow two different bitmaps got the same index and when I free the other one, the other one also gets freed. I really don't know how this is possible.
Well, I think this is solved now. Probably not though :rolleyes:

Wizzup?

2011-11-30 03:38:33

A try…except is not really a solution. :)
I can guarantee you that Simba's Find* methods do not free a bitmap, though.

E: By the way, the way you do it Simba should error on the FreeBitmap. So there's definitely SOMETHING changing 'bmp'. (Simba would error because you cannot free a bitmap that you have currently set as a target)