Grayscaling transparent gifs and pngs

I find that I end up custom painting a lot of the controls in Red Gate products, this is normally due to some gripe from our usability engineers – I was doing this today and wanted to gray scale some of the pngs when I need to show them disabled – This normally means loading up the excellent Paint.NET and grayscaling each one by hand – then I thought we can surely do this through code with GetPixel and SetPixel, my inital 0.33 of each of the color components didnt work that well and the images looked a little odd – a quick google turns up this: http://www.bobpowell.net/grayscale.htm which tells us to use a mix of 30% red, 59% green and 11% blue.

Giving us the following function: (From  http://www.bobpowell.net/grayscale.htm)

public

static Bitmap GrayScaleImage(Bitmap source)

{

Bitmap bm = new Bitmap(source.Width,source.Height);

for(int y=0;y<bm.Height;y++)

{

for(int x=0;x<bm.Width;x++)

{

Color c=source.GetPixel(x,y);

int luma = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11);

bm.SetPixel(x,y,Color.FromArgb(luma,luma,luma));

}

}

return bm;

}

However with our alpha transparency png’s this really doesnt work that well as you end up with little black borders, a quick tweak fixes this:

public static Bitmap GrayScaleImagePreserveTransparency(Bitmap source)

{

Bitmap bm = new Bitmap(source.Width,source.Height);

for(int y=0;y<bm.Height;y++)

{

for(int x=0;x<bm.Width;x++)

{

Color c=source.GetPixel(x,y);

int luma = (int)(c.R*0.3 + c.G*0.59+ c.B*0.11);

bm.SetPixel(x,y,

Color.FromArgb(c.A, luma,luma,luma));

}

}

return bm;

}