shadowrecon Posted April 12, 2012 Share Posted April 12, 2012 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.. Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 12, 2012 Share Posted April 12, 2012 Isn't this basically what GetBitmapAreaColors does? Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 12, 2012 Author Share Posted April 12, 2012 (edited) 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 April 12, 2012 by shadowrecon Quote Link to comment Share on other sites More sharing options...
Bixby Sayz Posted April 12, 2012 Share Posted April 12, 2012 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 xUnfortunately 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. Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 13, 2012 Share Posted April 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 13, 2012 Author Share Posted April 13, 2012 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] Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 13, 2012 Share Posted April 13, 2012 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 Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 13, 2012 Author Share Posted April 13, 2012 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? Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 13, 2012 Share Posted April 13, 2012 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. Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 14, 2012 Author Share Posted April 14, 2012 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. Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 14, 2012 Share Posted April 14, 2012 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. Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 14, 2012 Author Share Posted April 14, 2012 Yes, it's still godd practice to do so though, it makes it easier to differentiate between the value and pointer types. I tried adding the ^ to the line and it keep giving me not a pointer type? hmm.. im confused. Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 14, 2012 Share Posted April 14, 2012 Line isn't a PRGB32Array? Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 15, 2012 Author Share Posted April 15, 2012 (edited) 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 April 15, 2012 by shadowrecon Quote Link to comment Share on other sites More sharing options...
FHannes Posted April 15, 2012 Share Posted April 15, 2012 Looks legit... If it's a PRGB32Array, ^ should work... Quote Link to comment Share on other sites More sharing options...
shadowrecon Posted April 16, 2012 Author Share Posted April 16, 2012 I tried it but keep saying not a valid pointer type. ill do some research and see if i can find an example. Quote Link to comment Share on other sites More sharing options...