PDA

View Full Version : TBItmap scanline



AirPas
27-05-2011, 01:34 PM
from a simple test i did , i noticed that the scanline hasn't a sequential order address with the next scanline, i mean if i take the address of the last pixel in the first scanline and then increment the this address , i'll point to invalide memory location .

now if i want to travels the whole TBitmap without need of getting the address of evry scanline , i mean just get the first address and then increment it to the end of bitmap pixles .




var
p : ^integer;
begin
p := bmp.ScanLine[0];
Pinteger(integer(p)+(bmp.width + 1) )^ := $FFFF0000; // access violation
image1.Canvas.draw(0,0,bmp);

JSoftware
27-05-2011, 01:55 PM
There's not really a way you can do that

deathshadow
12-07-2011, 04:14 PM
You need to use canvas instead of scanline if you want to do that. I would suggest calculating the scanline offset manually instead of using the scanline property. Just be sure to check it's pixelFormat :D

Really,


p:=pointer(longword(bmp.canvas)+desiredScanLine*bm p.width*4);

Should do the trick. Is that REALLY so much harder than calling scanline? I doubt it.

Oh, and I REALLY suggest using longword instead of integer on these types of operations, you never know when the sign bit is going to mess with you.

honestly, the mere existance of the scanline method in tbitmap is probably why I stopped using it -- it makes image loads take longer setting up all those pointers.

AirPas
13-07-2011, 08:56 AM
thanks , but i changed the direction
i mean it was just my attempt to create a game from scratch (frame buffer) , instead of VCL i used API and CreateDIBSection (much easier) , but even i use assembly code for ploting pixels , i failed to make a smooth sprite movment .

now i am using SDL

AirPas
20-09-2011, 04:09 PM
hi again

could some one correct me , i've tryed to make a procedure that plot a given pixel ( x ,y , color) into TBitmap class



procedure SetScanLinePixel(x,y,c : integer; var _bmp : TBitmap);
type
pRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32768-1] of TRGBTriple;
var
raw : pRGBTripleArray;
begin
raw := _bmp.ScanLine[y];
raw[x].rgbtBlue := ( c and $ff);
raw[x].rgbtGreen := ( c shl 8 ) and $ff;
raw[x].rgbtRed:= ( c shl 16) and $ff; //error :constant expression violates subrange bounds
end;

i don't understand the last compiler error ,

LP
20-09-2011, 04:23 PM
Disable the compiler's range check error in project options or use {$R-} flag at top of your unit. Also change "c" to be Cardinal and change "shl" to "shr".

AirPas
21-09-2011, 08:35 AM
@Lifepower : thanks , i also didn't swap the color
so this is the correct code



procedure SetScanLinePixel(x,y: integer; c : cardinal; var _bmp : TBitmap);
type
pRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = array[0..32768-1] of TRGBTriple;
var
raw : pRGBTripleArray;
begin
raw := _bmp.ScanLine[y];
raw[x].rgbtRed := ( c and $ff);
raw[x].rgbtGreen := ( c shr 8 ) and $ff;
raw[x].rgbtBlue := ( c shr 16) and $ff;
end;

deathshadow
25-09-2011, 12:58 PM
I'd consider optimizing that down to a few less operations...



procedure SetScanLinePixel(x,y:integer; c:longword; var surface:TBitmap);
type
pRGBTriple=^tRGBTriple;
pWord=^word;
var
p:pRGBTriple;
begin
{ this typecast makes X add by multiples of 3 }
p:=pRGBTriple(surface.scanline[y])+x;
word(p^.g):=c and $0000FFFF;
p^.r:=(c shr 16) and $000000FF;
end;


Probably why NOBODY uses 24 bit bitmap formats -- I'd REALLY recommend upping to RGBA/32 bit format even if you aren't going to use the alpha channel, just for the speed boost, lesser code, etc, etc... Just not having pixels end up breaking qword boundaries would be a huge speedup.

Assuming built from RGBQuad instead of triple:


procedure SetScanLinePixel(x,y:integer; c:longword; var surface:TBitmap);
type
pLongWord=^longWord;
var
p:pLongWord;
begin
p:=pLongWord(surface.scanline[y])+x;
p^:=c;
end;


3 byte per pixel graphics sucks... slow, painfully bad math... there's a reason you rarely see anyone use it.

Mind you, the above works in FPC, no clue if delphi allows for that type of pointer math.

LP
26-09-2011, 04:24 AM
Probably why NOBODY uses 24 bit bitmap formats -- I'd REALLY recommend upping to RGBA/32 bit format even if you aren't going to use the alpha channel, just for the speed boost, lesser code, etc, etc... Just not having pixels end up breaking qword boundaries would be a huge speedup.
Also, 24-bit pixel format is not supported on any of the today's video cards. It's only useful for storage because you save some 1/4th of disk space. I wouldn't worry about the speed implications of the multiplication, on the modern CPUs (including Intel Atom) it's pretty fast; you'll be more limited by memory bandwidth anyway.


Mind you, the above works in FPC, no clue if delphi allows for that type of pointer math.
The same code for Delphi would be:


// 24-bit version
procedure SetScanLinePixel24(x, y: Integer; c: Cardinal; Image: TBitmap);
var
DestPtr: Pointer;
begin
DestPtr:= Pointer(NativeInt(Image.Scanline[y]) + x * 3);
// you can replace Move() with two lines of code moving a word and then a byte manually.
Move(c, DestPtr^, 3);
end;

// 32-bit version
procedure SetScanLinePixel32(x, y: Integer; c: Cardinal; Image: TBitmap);
begin
// for FPC, replace "NativeInt" with "PtrInt".
PLongWord(NativeInt(Image.Scanline[y]) + x * 4)^:= c;
end;

AirPas
26-09-2011, 07:12 AM
here is another procedure work with index instead of xy



procedure SetScanLineIndex32(indx:longword; c:cardinal; var image : Tbitmap);
begin
Plongword(longword(image.scanline[indx div image.Height]) + indx mod image.Width * 4)^ := c;
end;

marcov
19-11-2011, 11:19 PM
Also, 24-bit pixel format is not supported on any of the today's video cards.


Not internally, but it is as texture. If you don't use alpha, it is better to keep it 24-bit, and only expand during uploading, otherwise you afaik waste videocard bandwidth (example: showing images from camera's)

And effective texture upload sizes aren't getting faster as quickly as rendering.

LP
20-11-2011, 12:51 AM
Not internally, but it is as texture. If you don't use alpha, it is better to keep it 24-bit, and only expand during uploading, otherwise you afaik waste videocard bandwidth (example: showing images from camera's)
You are wrong. If the texture format is not supported by video card (which is the case of 24-bit pixel format on most video hardware), then expanding it before uploading does not reduce bandwidth, it only saves disk space. In addition, converting 24-bit format to 32-bit upon loading is quite slow as pixel data is not memory aligned so you'll be wasting a lot of CPU power just to load the image. I would argument exactly the opposite, huge disk space is cheap these days so you'd better off storing 32-bit pixel format instead of inducing massive overhead just to avoid saving one additional byte per pixel on disk (and there are other more efficient ways to save disk space, e.g. compression).

P.S. If you have doubts, please download DirectX SDK and use Caps Viewer to see that effectively, no 24-bit texture format is supported, either "internally" (whatever you meant by that) or not.