C# Image Processing Performance - Unsafe vs. Safe code, Part II
published mar 14 2008
In Part I of this article, I outlined a method of performing pixel-level operations on an image that required neither unsafe code, nor the use of the
SetPixel methods, which are notoriously slow. The one thing I neglected to include was an actual comparison of the
IntPtr and pointer methods with the
GetPixel\SetPixel methods. As such, I present such a method below. It looks tantalizingly simple, but we’ll soon see that it is basically worthless.
As outlined in the previous post, I created a form that would allow me to run each threshold method repeatedly to find an average time per threshold operation. The results are given in the table below. For these tests, an arbitrary threshold of 125 was chosen. The image used 24 bits-per-color and had a size of 479 x 700 pixels.
|Algorithm||Total Time (ms)||% Difference|
||238,299 (~4 min.)||122,734%|
The first observation is simple:
GetPixel\SetPixel SUCKS! It took longer to do 10 operations using that method than it took to do 500 using either of the other two. We also see that the
IntPtr method, while not a terrible alternative (if, for some reason, the use of unsafe code was strictly not allowed) is also moderately slower than the pointer method.
I wrote up a simple test program to perform these tests. It also includes a subjective test, wherein one can select the threshold method and then move a slider to set different threshold values to see how quickly the image changes. The subjective test agrees with the results above.
If you poke around in the program a bit, you’ll also discover a couple of extras, including some tests of using a square-root-of-squares type method for finding the magnitude of a pixel (applied to thresholding, and grayscaling). There is also a method that allows convolution filters to be applied to the image, though editing the filters is very cumbersome. Expect to see new, more-complete versions this program in the future.
Most of the code from this series is in Process.cs