Link to home
Start Free TrialLog in
Avatar of bogieman_
bogieman_

asked on

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.
Avatar of TheNeil
TheNeil

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
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.
ASKER CERTIFIED SOLUTION
Avatar of Vovbager
Vovbager

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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
Avatar of bogieman_

ASKER

Cheers - that was all I needed.