Pixel routines

I want to be able to quikely run through all the pixels in an image/canvas so I can change them, or do whatever I want, and at the moment, all I do is:

for x:=0 to 50 do begin
for y:=0 to 50 do begin
MyCanvas.pixels[x,y]:=RGB(random(255),random(255),random(255));
end;
end;

...but this goes very slowly.  Is there a faster method?  I don't know if this is very hard, but will raise the points if it is worth it.
LVL 1
bogieman_Asked:
Who is Participating?

[Webinar] Streamline your web hosting managementRegister Today

x
 
VovbagerConnect With a Mentor Commented:
hi bogieman

try to use ScanLine metod
ScanLine metod is very faster than canvas.pixel

for example

procedure xxx(tmpBitmap: TBitmap);
var tmpBuffer:PByteArray;
    i, j: Integer;
begin

tmpBitmap.PixelFormat:=pf24bit;
for j:=0 to tmpBitmap.Height-1 do
  begin
  tmpBuffer:=tmpBitmap.ScanLine[j];
  for i:=0 to tmpBitmap.Width-1 do
    begin
    tmpBuffer[i+0]:=255;
    tmpBuffer[i+1]:=255;
    tmpBuffer[i+2]:=255;
    end;
  end;
end;
0
 
TheNeilCommented:
Using the pixels method is slow but you can speed things up by making sure that everything is done in memory rather than on screen. If that isn't fast enough (or you're already doing it), switch over to using scanlines. They aren't easy to use but once you get the hang of them then it's a doddle and works like lightning.

The Neil

PS Yes, I'd raise the points
0
 
florisbCommented:
Canvas.pixels[x,y]:=random(16581375) would make a small difference.

with 0..500 it takes about 0.3 seconds here... ...too slow?

You'll have to loop, this bottleneck you can't really make shorter, assembly?

I don;t know why, but you should call Randomize; before you call Random;

procedure TForm1.Button1Click(Sender: TObject);
var
x,y : integer;
begin
Randomize;
for x:=0 to 500 do
  begin
  for y:=0 to 500 do
    begin
    Canvas.pixels[x,y]:=random(16581375);//RGB(); //random(255),random(255),random(255));
    end;
  end;
end;

Floris.
0
 
edeyCommented:
just a couple of points to consider:

1)Moving to a scanline (of DIB) solution would require rewriting your pixel access function for every possible pixel format, this is not a prob if you know what the pf is going to be

2)there is some overhead (however slight) with calling a method, if you do not want to code your own dib class (not too difficult if you're comfortable with the win32 api) you could change the above to:

procedure xxx(tmpBitmap: TBitmap);
var tmpBuffer:PByteArray;
    i, j, delta: Integer;
begin

tmpBitmap.PixelFormat:=pf24bit;
tmpBuffer := tmpBitmap.scanline[0];
delta := integer(tmpBitmap.scanline[1])-integer(tmpbuffer);
for j:=0 to tmpBitmap.Height-1 do
  begin
  for i:=0 to tmpBitmap.Width-1 do
    begin
    tmpBuffer[i+0]:=255;
    tmpBuffer[i+1]:=255;
    tmpBuffer[i+2]:=255;
    end;
  tmpBuffer := PByteArray(integer(tmpBuffer)+delta);
  end;
end;


it should be noted, though that the above makes very little difference, and if you're going to resort to hacking the vcl that way, it would be safer/cleaner/more elegant to code your own DIB class (has other pro's as well)


GL
Mike
0
 
bogieman_Author Commented:
Cheers - that was all I needed.
0
All Courses

From novice to tech pro — start learning today.