Accelerating bitmap grayscale conversion, is OpenMP an option in C#?

You’ll hit a couple of speed-bumps if OpenMP is on your radar. OpenMP is a multi-threading library for unmanaged C/C++, it requires compiler support to be effective. Not an option in C#.

Let’s take a step back. What you’ve got now is as bad as you can possibly get. Get/SetPixel() is dreadfully slow. A major step would be to use Bitmap.LockBits(), it gives you an IntPtr to the bitmap bits. You can party on those bits with an unsafe byte pointer. That will be at least an order of magnitude faster.

Let’s take another step back, you are clearly writing code to convert a color image to a gray-scale image. Color transforms are natively supported by GDI+ through the ColorMatrix class. That code could look like this:

public static Image ConvertToGrayScale(Image srce) {
  Bitmap bmp = new Bitmap(srce.Width, srce.Height);
  using (Graphics gr = Graphics.FromImage(bmp)) {
    var matrix = new float[][] {
        new float[] { 0.299f, 0.299f, 0.299f, 0, 0 },
        new float[] { 0.587f, 0.587f, 0.587f, 0, 0 },
        new float[] { 0.114f, 0.114f, 0.114f, 0, 0 },
        new float[] { 0,      0,      0,      1, 0 },
        new float[] { 0,      0,      0,      0, 1 }
    };
    var ia = new System.Drawing.Imaging.ImageAttributes();
    ia.SetColorMatrix(new System.Drawing.Imaging.ColorMatrix(matrix));
    var rc = new Rectangle(0, 0, srce.Width, srce.Height);
    gr.DrawImage(srce, rc, 0, 0, srce.Width, srce.Height, GraphicsUnit.Pixel, ia);
    return bmp;
  }
}

Credit to Bob Powell: How to convert a colour image to grayscale for the above code.

Leave a Comment