Interesting Pixel-Plotting Efficiency Test Results

I recently ran a little experiment to see which would be the fastest way to plot a bunch of single pixels using the methods available in the System.Drawing namespace.  It turns out, for those who haven't looked, that there is no set-pixel type method because everything is built to work with various unit scales -- some of which have no use for single-pixel work.

I tested DrawRectangle, FillRectangle, DrawEllipse, FillEllipse, DrawLine, DrawImage (using a 1x1 rectangle from a memory bitmap that had been pre-built to have a bunch of randomly colored pixels), and even DrawString (at the right point size, the period is essentially a single pixel).  I ran each one through 100,000 pixels and stopwatch timed each one ... turns out that they were all within a couple tenths of a second of one another (less than 1% difference), except for DrawString -- that one was a couple seconds slower across 100,000 dots than the others.

So, I guess that means it really doesn't matter how you go about doing it ... just pick the method that fits the best into the code and gives the best on screen results.

(btw, I am still working on the "It's All About the Cameras" post that I promised last time ...)

Published Monday, February 09, 2009 8:20 PM by MattWorden
Filed under: ,

Comments

# re: Interesting Pixel-Plotting Efficiency Test Results

Have you tried locking the bitmap and doing some direct memory access? I'm sure that would beat all your pixel plotting tests you did before. Ofcourse, you lock only once, then draw 100,000 pixels and then unlock. If you have to draw a lot of pixels manually, then that is the way to go. Little example:

BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Size.Width, bitmap.Size.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

int* pixels = (int*)bmpdata.Scan0.ToPointer());

...draw your pixels here by simply writing to the memory that 'pixels' points to...

bitmap.UnlockBits(bmpdata);

Keep in mind that this example expects your bitmap to be in 32bits ARGB format. You can lock other formats as well, but then you have to take that into account when accessing the memory.

Tuesday, February 10, 2009 2:30 PM by codeimp

# re: Interesting Pixel-Plotting Efficiency Test Results

Hi codeimp ...

(btw, You may be the only person reading this blog!) ;-D

I did not try the LockBits approach.  Since I'm using VB.Net, I would need to do a couple extra steps, since I can't directly access memory pointers (unless there's a way that I haven't seen yet).

So, I would need to create a byte array of the proper size and do a Marshall.Copy to get the bit data into that array ... do my modifications to that array ... then Marshall.Copy it back to the locked bitmap memory.

It would probably still be faster by an order of magnitude.

I can see using that for pixel-sized particles & dust, etc., although I would need to change from having each particle draw itself to having the particle manager class draw all of the particles at once ... but that might still be a win.

Thanks again for your suggestion ... I'll give it a whirl and let you know my results.

-Matt

Tuesday, February 10, 2009 3:21 PM by MattWorden