I’ve been working on a new open source project this past week and had a requirement to get ARGB value of every pixel in the image. I thought ‘OK easy, just use Bitmap.GetPixel()‘! At first I was using small images so there was not a problem, but as the size of the image increased, the performance of the application just dropped!
After a little bit of digging around I found the answer right under my nose! Rob Miles recently wrote an article on Image Manipulation in Windows Mobile 5.0 for the OpenNETCF Community site. The section that stood out to me was ‘Speeding up Bitmap Access’. I took the techniques he showed in the article and implemented them in my code. The result was an average savings of 11.5s to grab the pixel ARGB values.
Here is the original code (average for time for a 324×324 image was 12s):
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
intImage[x][y] = image.GetPixel(x, y).ToArgb();
}
}
And here is the new code (average for time for a 324×324 image was 0.5s):
unsafe
{
BitmapData bd = image.LockBits(new Rectangle(0, 0, image.Width, image.Height),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
int sourceWidth = image.Width * System.Runtime.InteropServices.Marshal.SizeOf(typeof(PixelData));
if (sourceWidth % 4 != 0)
sourceWidth += (4 – (sourceWidth % 4));
Byte* bitmapBaseByte;
bitmapBaseByte = (Byte*)bd.Scan0.ToPointer();
PixelData* pPixel;
for (int y = 0; y < height; y++)
{
pPixel = (PixelData*)(bitmapBaseByte + y * sourceWidth);
for (int x = 0; x < width; x++)
{
intImage[x][y] = (int)((0xff << 0x18) | (pPixel->red << 0x10) | (pPixel->green << 8) | pPixel->blue);
pPixel++;
}
}image.UnlockBits(bd);
}
By using unsafe block and directly accessing the bitmap data in memory we save a huge 11.5s on average. If you want a more detailed explanation on how the code works read the article.
For those interested here is the image I was testing with: