I’m working with a customer and they have a requirement to convert an image to gray scale. Using direct pixel access method discussed here and extension methods it’s pretty straight forward.
public static Bitmap ModifyColors(this Bitmap image, double redChange, double greenChange, double blueChange)
{
if (image == null)
return null;
Bitmap newBitmap = (Bitmap)image.Clone();
int width = newBitmap.Width;
int height = newBitmap.Height;
unsafe
{
BitmapData bd = newBitmap.LockBits(new Rectangle(0, 0, newBitmap.Width, newBitmap.Height),
ImageLockMode.ReadWrite,
PixelFormat.Format24bppRgb);
int sourceWidth = newBitmap.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;
int redVal;
int greenVal;
int blueVal;
for (int y = 0; y < height; y++)
{
pPixel = (PixelData*)(bitmapBaseByte + y * sourceWidth);
for (int x = 0; x < width; x++)
{
redVal = (int)(pPixel->red * redChange) + (int)(pPixel->green * greenChange) + (int)(pPixel->blue * blueChange);
if (redVal < 0) redVal = 0;
if (redVal > 255) redVal = 255;
pPixel->red = (byte)redVal;
greenVal = (int)(pPixel->red * redChange) + (int)(pPixel->green * greenChange) + (int)(pPixel->blue * blueChange);
if (greenVal < 0) greenVal = 0;
if (greenVal > 255) greenVal = 255;
pPixel->green = (byte)greenVal;
blueVal = (int)(pPixel->red * redChange) + (int)(pPixel->green * greenChange) + (int)(pPixel->blue * blueChange);
if (blueVal < 0) blueVal = 0;
if (blueVal > 255) blueVal = 255;
pPixel->blue = (byte)blueVal;
pPixel++;
}
}
newBitmap.UnlockBits(bd);
}
return newBitmap;
}
Basically all we are doing is getting direct access to the pixel data using a pointer and modifying the RGB values with the parameters sent by the user. In our main code where we want to convert the image, lets say we have an image in a PictureBox that we want to convert and store the result in a new PictureBox all we have to do is call one line of code:
pictureBox2.Image = pictureBox1.Image.ToGrayScale();
Here is a sample of the input/output:

And you can download the source for converting an image to grayscale here.