Using SetPixel

S

Seabass

Hello everyone,

I have to do an image viewer for an exotic format so I want to know
how to place pixels somewhere on the form or on some object.

I tried doing this but it works incredibly slow.

{

Bitmap bmp = new Bitmap(this.Width, this.Height);

for (int i = 0; i < this.Width; i++)

{

for (int j = 0; j < this.Height; j++)

{

bmp.SetPixel(i, j, Color.Blue);

}

}

Graphics g = this.CreateGraphics();

g.DrawImage(bmp, new Point(0, 0));

bmp.Dispose();

}
 
N

Nicholas Paldino [.NET/C# MVP]

Seabass,

The problem with this is that as soon as your form receives a refresh
windows message, it will paint over whatever you drew already.

What you need to do is attach to the Paint event, or override the
OnPaint method for the control/form you want to display this in.

You might not want to create the bitmap every time, but rather, only
when something changes.
 
P

Peter Duniho

I have to do an image viewer for an exotic format so I want to know
how to place pixels somewhere on the form or on some object.

I tried doing this but it works incredibly slow. [...]

In addition to what Nicholas wrote (he doesn't seem to have addressed your
specific question, but his comments *are* relevant to what you're doing,I
think)...

The reason your code is so slow is that you're setting one pixel at a
time. It's very expensive, performance-wise, to go between the
application and the bitmap, and you're incurring that cost once for every
pixel in the image. Icing on the cake is doing all that work to a bitmap
and then copying the bitmap to your destination, but that's an
insignificant cost compared to the pixel-at-a-time approach.

Fortunately, all graphics APIs offer better ways to do this sort of thing,
including .NET's. :)

In your case, you seem to be setting all of the pixels in the image to
blue. So rather than the nested loops calling SetPixel(), use this:

using (SolidBrush brush = new SolidBrush(Color.Blue))
{
g.FillRectangle(brush, new Rectangle(new Point(0,0), this.Size));
}

Noting of course the advice Nicholas gave you. If you want your effort to
be persistent, you need to at a minimum to the above in the OnPaint()
method for your form. If you're doing something more complicated than
just filling it with blue, you may well want to cache your drawing to a
bitmap (you can draw to a bitmap by calling the Graphics.FromImage()
method to get a Graphics instance that will draw to the bitmap), and then
just use the DrawImage() method to draw that image to the form in its
OnPaint() method.

Pete
 
K

KWienhold

I have to do an image viewer for an exotic format so I want to know
how to place pixels somewhere on the form or on some object.
I tried doing this but it works incredibly slow. [...]

In addition to what Nicholas wrote (he doesn't seem to have addressed your
specific question, but his comments *are* relevant to what you're doing, I
think)...

The reason your code is so slow is that you're setting one pixel at a
time. It's very expensive, performance-wise, to go between the
application and the bitmap, and you're incurring that cost once for every
pixel in the image. Icing on the cake is doing all that work to a bitmap
and then copying the bitmap to your destination, but that's an
insignificant cost compared to the pixel-at-a-time approach.

Fortunately, all graphics APIs offer better ways to do this sort of thing,
including .NET's. :)

In your case, you seem to be setting all of the pixels in the image to
blue. So rather than the nested loops calling SetPixel(), use this:

using (SolidBrush brush = new SolidBrush(Color.Blue))
{
g.FillRectangle(brush, new Rectangle(new Point(0,0), this.Size));
}

Noting of course the advice Nicholas gave you. If you want your effort to
be persistent, you need to at a minimum to the above in the OnPaint()
method for your form. If you're doing something more complicated than
just filling it with blue, you may well want to cache your drawing to a
bitmap (you can draw to a bitmap by calling the Graphics.FromImage()
method to get a Graphics instance that will draw to the bitmap), and then
just use the DrawImage() method to draw that image to the form in its
OnPaint() method.

Pete

In case you have to work with small portions of the image (maybe even
pixel by pixel), you should consider looking at this link:
http://www.bobpowell.net/lockingbits.htm
While it is a little complicated, working with LockBits is blazing
fast compared to the normal SetPixel approach.
I use this myself to implement custom grayscale conversions and such.

Sincerely,
Kevin Wienhold
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top