# Converting an Image (well, Bitmap really) to Grayscale

First thought – convert the picture to greyscale and increase the contrast to help any kind of edge-detection work.  Some searching found me Bob Powell's handy guide to increasing contrast and converting to grayscale via ColorMatrix.  With Wikipedia’s explanation of “naive” matrix multiplication in hand I cobbled up a converter that takes a bitmap and returns a grayscaled version.

``````     public class GreyscaleBitmap
{
// Magic conversion to greyscale matrix
static float[][] _grayScaleMatrix = new float[][] {
new float[] {.3f, .3f, .3f, 0, 0},
new float[] {.59f, .59f, .59f, 0, 0},
new float[] {.11f, .11f, .11f, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
};

// Doubles contrast
static float[][] _increaseContrast = new float[][] {
new float[] {2, 0, 0, 0, 0},
new float[] {0, 2, 0, 0, 0},
new float[] {0, 0, 2, 0, 0},
new float[] {0, 0, 0, 1, 0},
new float[] {0, 0, 0, 0, 1}
};

// Dumb and slow.
static float[][] MatrixMult2(float[][] first, float[][] second)
{
float[][] result = new float[];

for (int i = 0; i < 5; i++)
result[i] = new float;

for (int j = 0; j < 5; j++)
for (int k = 0; k < 5; k++)
for (int i = 0; i < 5; i++)
result[i][j] += first[i][k] * second[k][j];

return result;
}

// Only bother making one of these
static ColorMatrix _matrix = new ColorMatrix(MatrixMult2(_grayScaleMatrix, _increaseContrast));

// Cache this as well?
static ImageAttributes GetAttributes()
{
ImageAttributes result = new ImageAttributes();
result.SetColorMatrix(_matrix);
return result;
}

public static Bitmap Convert(Bitmap bmp)
{
Bitmap newBitmap = new Bitmap(bmp.Width, bmp.Height, PixelFormat.Format24bppRgb);

using (Graphics g = Graphics.FromImage(newBitmap))
{
Rectangle r = new Rectangle(0, 0, newBitmap.Width, newBitmap.Height);
g.DrawImage(bmp, r, 0, 0, bmp.Width, bmp.Height, GraphicsUnit.Pixel, GetAttributes());
}

return newBitmap;
}
}
``````

Now, in another world the output image format would be 16bpp grayscale directly, instead of being re-encoded in 24bpp RGB.  As a result, my eventual scanner will have to convert back from RGB to a grayscale value again.  Not a great start, but hey – conversion to grayscale!