Board index » delphi » Looking for fast "PutPixel" procedure

Looking for fast "PutPixel" procedure

Hi all,

I am looking for an efficient way to set pixels in a bitmap or on a
canvas (Delphi 2.) Executing "Bitmap.Canvas.Pixels[x,y]:=clBlack" is
very slow - it does about 60,000 pixels/second on my 166Mhz Pentium.
In my application, I do about 22 extended arithmetic operations per
pixel (including sqrt/sin/cos), and even then the Pixels property
takes 8 times longer to execute than my code. In the past under DOS,
the time to "PutPixel" was a tiny fraction of the calculation time. I
cannot construct the image I am building using any other method such
as lines, etc.

I thought that creating a bitmap in memory would be faster than
plotting directly to the canvas, but it isn't. An outline of my code
is:

    Bitmap := TBitMap.Create;
    Bitmap.Height := Image1.Height;
    Bitmap.Width := Image1.Width;
    { Do calculations and call this approx 40,000 times: }
        Bitmap.Canvas.Pixels[x,y] := clBlack;
    Image1.Picture.Graphic := Bitmap;

I have tried various options such as "IgnorePalette := True", but it
makes no difference.

Does anybody know of a way of getting to the bitmap in memory? I am
sure I could write code to "twiddle bits" there much faster than the
Pixels property. Or is there any other way?

Chris

=======================================================
Chris Williams               chris.willi...@pixie.co.za
Tel: +27 331 961066 (local 0331 961066) 07:00-19:00 GMT
Fax: +27 331 961066 (local 0331 961066) 22:00-04:00 GMT
-------------------------------------------------------

Quote
>>>>>>>>  See "The Number Crunching Page" at:  <<<<<<<<
>>> http://www.geocities.com/SiliconValley/Bay/9187 <<<

Lots of interesting facts & figures ... Free software!!
=======================================================

-------------------==== Posted via Deja News ====-----------------------
      http://www.dejanews.com/     Search, Read, Post to Usenet

 

Re:Looking for fast "PutPixel" procedure


Quote
On Sun, 17 Aug 1997 00:51:17 -0600, chris.willi...@pixie.co.za wrote:

Not quite what you might want, but the form.canvas.pixels[] work a lot
faster (!). However it does not withstand the windows refreshing...
Just to let you know. i've seen some code somewhere, where they've
used an array to bitmap copy. this array fillling must have been a lot
faster as well.
'nough hints for now, i don't have exact answers. (delphi3 has
scanlines, which work faster as well).
bye. Marco.
Quote
>Hi all,

>I am looking for an efficient way to set pixels in a bitmap or on a
>canvas (Delphi 2.) Executing "Bitmap.Canvas.Pixels[x,y]:=clBlack" is
>very slow - it does about 60,000 pixels/second on my 166Mhz Pentium.
>In my application, I do about 22 extended arithmetic operations per
>pixel (including sqrt/sin/cos), and even then the Pixels property
>takes 8 times longer to execute than my code. In the past under DOS,
>the time to "PutPixel" was a tiny fraction of the calculation time. I
>cannot construct the image I am building using any other method such
>as lines, etc.

>I thought that creating a bitmap in memory would be faster than
>plotting directly to the canvas, but it isn't. An outline of my code
>is:

>    Bitmap := TBitMap.Create;
>    Bitmap.Height := Image1.Height;
>    Bitmap.Width := Image1.Width;
>    { Do calculations and call this approx 40,000 times: }
>        Bitmap.Canvas.Pixels[x,y] := clBlack;
>    Image1.Picture.Graphic := Bitmap;

>I have tried various options such as "IgnorePalette := True", but it
>makes no difference.

>Does anybody know of a way of getting to the bitmap in memory? I am
>sure I could write code to "twiddle bits" there much faster than the
>Pixels property. Or is there any other way?

>Chris

>=======================================================
>Chris Williams               chris.willi...@pixie.co.za
>Tel: +27 331 961066 (local 0331 961066) 07:00-19:00 GMT
>Fax: +27 331 961066 (local 0331 961066) 22:00-04:00 GMT
>-------------------------------------------------------
>>>>>>>>>  See "The Number Crunching Page" at:  <<<<<<<<
>>>> http://www.geocities.com/SiliconValley/Bay/9187 <<<
>Lots of interesting facts & figures ... Free software!!
>=======================================================

>-------------------==== Posted via Deja News ====-----------------------
>      http://www.dejanews.com/     Search, Read, Post to Usenet

Re:Looking for fast "PutPixel" procedure


In article <871796762.9...@dejanews.com>, chris.willi...@pixie.co.za says...

Quote
>Does anybody know of a way of getting to the bitmap in memory? I am
>sure I could write code to "twiddle bits" there much faster than the
>Pixels property. Or is there any other way?

Take a look at CreateDIBSection.  Using this API function, you can create a
bitmap with the ability to write directly to a pointer to the bits.

--
Chris Hill
hil...@cs.purdue.edu

Re:Looking for fast "PutPixel" procedure


Quote
chris.willi...@pixie.co.za wrote:

: Hi all,

: I am looking for an efficient way to set pixels in a bitmap or on a
: canvas (Delphi 2.) Executing "Bitmap.Canvas.Pixels[x,y]:=clBlack" is
: very slow - it does about 60,000 pixels/second on my 166Mhz Pentium.
[snip]
:     { Do calculations and call this approx 40,000 times: }
:         Bitmap.Canvas.Pixels[x,y] := clBlack;
:     Image1.Picture.Graphic := Bitmap;

Try the API call setpixel.  I've been told it is a LOT faster than
setting the canvas pixels thingo.  I just looked it up in the D1 help
(thats all we have at uni), and i beleve it still exists in D2.  No idea
about D3.

hope it helps

wooz

Re:Looking for fast "PutPixel" procedure


Quote
> Try the API call setpixel.  I've been told it is a LOT faster than
> setting the canvas pixels thingo.  I just looked it up in the D1 help
> (thats all we have at uni), and i beleve it still exists in D2.  No idea
> about D3.

I've just tried using the SetPixel API function (under Delphi 2.01) and I
can't get it to run any quicker than by adressing the Pixels[] collection
of the canvas.  Here's the simplistic code I've been using...

var

result,xp,yp : integer;

begin

for xp:=0 to form1.clientwidth-1 do
for yp:=0 to form1.clientheight-1 do
    setpixel(form1.canvas.handle,xp,yp,0);

form1.refresh;

end;

Any idea how I can speed this little routine up?

Best regards,

Jon Souter
Email: Jon.Sou...@Dial.Pipiex.Com

Re:Looking for fast "PutPixel" procedure


Quote
"Jon Souter" <jon.sou...@gestetner.com> wrote:
>> Try the API call setpixel.  I've been told it is a LOT faster than
>> setting the canvas pixels thingo.  I just looked it up in the D1 help
>> (thats all we have at uni), and i beleve it still exists in D2.  No idea
>> about D3.
>I've just tried using the SetPixel API function (under Delphi 2.01) and I
>can't get it to run any quicker than by adressing the Pixels[] collection
>of the canvas.  Here's the simplistic code I've been using...
>Any idea how I can speed this little routine up?
>Best regards,
>Jon Souter
>Email: Jon.Sou...@Dial.Pipiex.Com

pipex.com I suspect...

Jon,

The secret here is not fancy tips and tricks but principle. Take a
step *back* for the moment :-).

Most of the Win API calls in this section are mainly used for drawing
windows controls, *not* for high speed graphics work. Example:

Let's say you've just uncovered a form and a button on it needs to
redraw.

Windows sends a message to the application, which takes it into the
message handler loop, does various things to it, and sends it to the
button. The Button object in delphi is just a wraparound of a few
windows API functions.. these windows API functions check for various
overlaps, window states, default colours, and a million and one other
things before anything gets drawn.

Each time you go for setpixel .... *for every single pixel* you try to
draw, you are calling windows, which checks the location and state of
*every single window* before drawing the pixel in order to make sure
it's not accidentally drawing it on top of someone elses application.
In this case it takes between 50,000 and 5,000,000 clock cycles just
to change a simple little pixel.

If you use a DIBSection, this is all changed. Windows doesn't
mollycoddle everything for you.... you just blast the data straight
into the DIBSection memory, and when *you* want to do it (like once
you've finished setting the memory values), you say to windows "Hey Mr
Operating System... I think you might like to update this window based
on this block of memory", which it will then do once for the image...
not once for every pixel!!!!

I had to fill out a 1024x768 display like this... using SetPixels it
took about 3 hours.... using a DIBSection, it took about 30
milliseconds.

MH.
***********************************************
Martin Harvey
By popular request, email addresses are now in plain text.
Uni email: mc...@hermes.cam.ac.uk
Home email: mc...@harvey27.demon.co.uk
Uni web pages: http://www-stu.pem.cam.ac.uk/~mch24/
***********************************************

Re:Looking for fast "PutPixel" procedure


Quote
hil...@cs.purdue.edu (Chris Hill) wrote:
>In article <871796762.9...@dejanews.com>, chris.willi...@pixie.co.za says...
>>Does anybody know of a way of getting to the bitmap in memory? I am
>>sure I could write code to "twiddle bits" there much faster than the
>>Pixels property. Or is there any other way?
>Take a look at CreateDIBSection.  Using this API function, you can create a
>bitmap with the ability to write directly to a pointer to the bits.
>--
>Chris Hill
>hil...@cs.purdue.edu

I've got a DIBSection example that I seem to roll out every month or
two when someone needs it.... it's got the added quirk that the
section is updated in an independent thread...

MH.
***********************************************
Martin Harvey
By popular request, email addresses are now in plain text.
Uni email: mc...@hermes.cam.ac.uk
Home email: mc...@harvey27.demon.co.uk
Uni web pages: http://www-stu.pem.cam.ac.uk/~mch24/
***********************************************

Re:Looking for fast "PutPixel" procedure


Quote
Jon Souter (jon.sou...@gestetner.com) wrote:

: I've just tried using the SetPixel API function (under Delphi 2.01) and I
: can't get it to run any quicker than by adressing the Pixels[] collection
: of the canvas.  Here's the simplistic code I've been using...

sorry, I hadn't actually tried it myself.

: Any idea how I can speed this little routine up?

How about SetPixelV, the help file reckons it is faster, coz it doesn't
return the value of the color used, just a true or false.

Once again, i havent used it so i cant actually promise that it is faster.

Let me know how you get on coz I'm in the process of writing a fractal
generator and I too am getting sick of how long it takes.  Any tips on
speeding up calculations would be MUCH apreciated

good luck

wooz

Re:Looking for fast "PutPixel" procedure


Quote
Daniel Findley wrote:
> [...]

> Try the API call setpixel.  I've been told it is a LOT faster than
> setting the canvas pixels thingo.  I just looked it up in the D1 help
> (thats all we have at uni), and i beleve it still exists in D2.  No idea
> about D3.

        SetPixel is an API function, so it certainly exists in D3.
Whoever told you it was lots faster than using Pixels lied - almost
all of the overhead in assigning a color to Pixels[x,y] is in
calling SetPixel.

        The traditional right way to do this sort of thing is via
the DIB functions - in D3 you can use TBitmap.Scanline instead.

--
David Ullrich

sig.txt not found

Re:Looking for fast "PutPixel" procedure


Quote
Martin Harvey wrote:
> [...]

> I've got a DIBSection example that I seem to roll out every month or
> two when someone needs it.... it's got the added quirk that the
> section is updated in an independent thread...

        You know TBitmap is much improved in D3 - in particular
it has two new properties PixelFormat and ScanLine that let
you handle this sort of thing very easily.

--
David Ullrich

sig.txt not found

Re:Looking for fast "PutPixel" procedure


HI

Quote
Jon Souter wrote:

[snip]

Quote
> var

> result,xp,yp : integer;

> begin

> for xp:=0 to form1.clientwidth-1 do
> for yp:=0 to form1.clientheight-1 do
>     setpixel(form1.canvas.handle,xp,yp,0);

> form1.refresh;

> end;

> Any idea how I can speed this little routine up?

What you must do is this :

var MyHdc:hdc;
begin
MyHdc:=form1.canvas.handle;
for xp:=0 to form1.clientwidth-1 do
for yp:=0 to form1.clientheight-1 do
    setpixel(MyHdc,xp,yp,clwhite);

form1.refresh;

end;

the method to fetch the handle to the canvas is the slowest part of the whole
thing, just keep it out of the loop.

hope it helps

Stig

Other Threads