Jump to content
shadowrecon

Scanline + T2DIntArray

Recommended Posts

Okay ive manage to finally figure out how to use scanline with scar, but now i have more of a logic error, im trying to get the array to have the x cord as first set of arrays and y cord as second set of arrays but right now im backwards y is first x is second. I could just use it as it is but im curious if anyone has any ideas that could fix this problem, if there isnt a quick and effective method i guess ill just have to get use to it for this project =/

 

[scar]

Function GMRL_GetBitmapRGBA(Const BMP: Integer): T2DRGBArray; stdCall;

var

TBMP: TBitmap;

W, H, I, II: Integer;

Line: PRGB32Array;

begin

if not BitmapAssigned(Bmp) then

raise Exception.Create('Bitmap not assigned');

GetBitmapSize(Bmp, W, H);

TBMP := TBitmap.Create;

TBMP.SetSize(W, H);

BitBlt(TBMP.Canvas.Handle, 0, 0, TBMP.Width, TBMP.Height, GetBitmapDc(BMP), 0, 0, SRCCOPY);

TBMP.PixelFormat := pf32bit;

for I := 0 to (H - 1) do // y value

Begin

Line := TBMP.ScanLine;

SetLength(Result, Length(Result) + 1);

for II := 0 to (W - 1) do // x value

Begin

SetLength(Result,Length(Result) + 1);

Result[iI].R := Line[iI].R;

Result[iI].G := Line[iI].G;

Result[iI].B := Line[iI].B;

Result[iI].A := Line[iI].A;

End;

End;

Line := nil;

TBMP.Free;

End;

[/scar]

 

Edit: I ment T2D Array not T2DIntArray in title..

Link to comment
Share on other sites

Isn't this basically what GetBitmapAreaColors does?

Yes but instead of getting all of the colors im just getting the RGB values so i can use them for comparison ect. It works right now, but I was just wondering if there was a way to switch the X and Y because right now the point (10 , 15) is represented by Result[15][10] nothing major but could deff cause issues if you didnt know that its y then x

 

Note: getbitmapareacolors you have to set the target bitmap which is weird it should just have a parameter to put the bitmap in to it. Save a line of code here and there by that one addition. =p

Edited by shadowrecon
Link to comment
Share on other sites

the point (10 , 15) is represented by Result[15][10] nothing major but could deff cause issues if you didnt know that its y then x
Unfortunately this is a "feature" of the pascal language. One area where pascal is completely opposite from other languages. Not something you run into a lot but it can drive you crazy trying to figure it out. There are a few more quirks of pascal like this but can't recall them off the top of my head.
Link to comment
Share on other sites

Unfortunately this is a "feature" of the pascal language. One area where pascal is completely opposite from other languages. Not something you run into a lot but it can drive you crazy trying to figure it out. There are a few more quirks of pascal like this but can't recall them off the top of my head.

 

It actually has nothing to do with pascal. It's a result of the way the win32 api handles bitmap data, it uses a logical row structure which, when you store each row in an array results in an array with an index corresponding to the y coordinate. If you break up those arrays into individual pixels, you get arrays of x coordinates, resulting in the 2 dimensional array [y][x]. It may not seem logical from everyone's point of view, but it's the most logical way of going about this, as [x][y] would indicate a column structure, which is very inefficient to work with and not very logical either.

 

Consider this. If you are performing operations on an image, more often than not, you would get a pixel, then move on to the next one, and so on. With the [y][x] structure, this means moving in a 1 dimensional array, which is far more efficient to do than moving through a 2 dimensional array all the time.

Link to comment
Share on other sites

That does make since, you only need to change one number at a time until you reach the end of the line then move down to next line and do it over instead of incrementing x and y at the same time. Plus it read dirrectly from memory and its structured in that whole row format.

 

Im having problems with this function in scar, it runs fine returns the results i want but then scar crashes. =/

 

[scar]

Function GMRL_GetBitmapRGB(Const BMP:Integer): T2DRGBArray; stdcall; export;

var

TBMP: TBitmap;

W, H, I, II: Integer;

Line: PRGB32Array;

begin

if not BitmapAssigned(Bmp) then

raise Exception.Create('Bitmap not assigned');

GetBitmapSize(Bmp, W, H);

TBMP := TBitmap.Create;

Try

TBMP.SetSize(W, H);

TBMP.PixelFormat := pf32bit;

BitBlt(TBMP.Canvas.Handle, 0, 0, TBMP.Width, TBMP.Height, GetBitmapDc(BMP), 0, 0, SRCCOPY);

 

SetLength(Result, H);

for I := 0 to (H - 1) do

SetLength(Result, W);

 

for I := 0 to (H - 1) do // y value

Begin

Line := TBMP.ScanLine;

for II := 0 to (W - 1) do // x value

Begin

Result[iI].R := Line[iI].R;

Result[iI].G := Line[iI].G;

Result[iI].B := Line[iI].B;

Result[iI].A := Line[iI].A;

End;

End;

Finally

TBMP.Free;

End;

End;

 

Function GMRL_GetBitmapAreaRGB(Const BMP:Integer; Xs,Ys,Xe,Ye: Integer): T2DRGBArray; stdcall; Export;

Var

I,II,Y1,X1,W,H: Integer;

RGBA: T2DRGBArray;

Begin

if not BitmapAssigned(BMP) then

raise Exception.Create('Bitmap not assigned');

 

RGBA:= GMRL_GetBitmapRGB(BMP);

W := (Xe - Xs) + 1;

H := (Ye - Ys) + 1;

 

SetLength(Result, H);

for I := 0 to High(Result) do

SetLength(Result, W);

 

Y1 := 0; X1 := 0;

Try

for I := Ys to Ye do // Y

Begin

for II := Xs to Xe do // X

Begin

Result[Y1][X1].R := RGBA[iI].R;

Result[Y1][X1].G := RGBA[iI].G;

Result[Y1][X1].B := RGBA[iI].B;

Result[Y1][X1].A := RGBA[iI].A;

Inc(X1);

End;

Inc(Y1);

End;

Except

raise Exception.Create('[GMRL_GetBitmapAreaRGB] -> Array is not setup correctly!!');

End;

End;

[/scar]

Link to comment
Share on other sites

Well, first off, you really don't have any use for the Alpha channel, returning it it just a waste of CPU cycles... There also seems to be a bug in your GMRL_GetBitmapAreaRGB function, though maybe unrelated to your problem... What happens if your search is (partially) outside of your bitmap's edges?

 

---------- Post added at 06:09 PM ---------- Previous post was at 10:26 AM ----------

 

Also, on a sidenote, you should access those scanline pointers as Line[iI]^.A

Link to comment
Share on other sites

Well, first off, you really don't have any use for the Alpha channel, returning it it just a waste of CPU cycles... There also seems to be a bug in your GMRL_GetBitmapAreaRGB function, though maybe unrelated to your problem... What happens if your search is (partially) outside of your bitmap's edges?

 

---------- Post added at 06:09 PM ---------- Previous post was at 10:26 AM ----------

 

Also, on a sidenote, you should access those scanline pointers as Line[iI]^.A

 

Alrighty thanks for the input. I removed the GMRL_GetBitmapAreaRGB function because i could not get it to work for nothing. everytime it keep crashing scar. I looked over the code a 100 times. I was hoping the alpha channel would actually return a value but found out it always returns 255 so i guess removing would save cycles and memory thanks! As far as using the ^ after line do i need to change any other part of the code or just add the ^ like this -> Result[iI].R := line[ii]^.R ?

 

---------- Post added at 05:59 PM ---------- Previous post was at 05:58 PM ----------

 

also from one of your old examples you set line := nil do i need to do that or was the a old way of freeing the lines memory?

Link to comment
Share on other sites

That line looks ok. when you use a pointer type, you should use ^ to switch back to the value type, though it's possible the compiler compensates it.

 

Also from one of your old examples you set line := nil do i need to do that or was the a old way of freeing the lines memory?

 

Shouldn't be required, but back then in 2007 my understanding of Delphi wasn't quite as great as it is now.

Link to comment
Share on other sites

That line looks ok. when you use a pointer type, you should use ^ to switch back to the value type, though it's possible the compiler compensates it.

 

 

 

Shouldn't be required, but back then in 2007 my understanding of Delphi wasn't quite as great as it is now.

 

Oh alright so it gives the actually data and not the address of the data completely understand! i think the compiler compensates in 2009 because ive ran tons of test using scar as a base line with accurate results.

Link to comment
Share on other sites

Oh alright so it gives the actually data and not the address of the data completely understand! i think the compiler compensates in 2009 because ive ran tons of test using scar as a base line with accurate results.

 

Yes, it's still godd practice to do so though, it makes it easier to differentiate between the value and pointer types.

Link to comment
Share on other sites

Line isn't a PRGB32Array?

no it is a PRGB32Array, heres how i have it setup in my types unit

 TRGB32 = packed record
   B, G, R, A: Byte;
 end;
 TRGB32Array = packed array[0..MaxInt div SizeOf(TRGB32) - 1] of TRGB32;
 PRGB32Array = ^TRGB32Array;

 

Heres the unit where the procedure is located

http://subversion.assembla.com/svn/gmrl/GRML_Plugin/Units/uBitmaps.pas

Edited by shadowrecon
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
  • Create New...