views:

544

answers:

3

I have Bitmap. I want to apply median filter to my bitmap. But I can’t use GetPixel() and SetPixel() because speed is very important factor for me. I need very fast way to do it. May be it can be done with a Graphics.DrawImage(Image, Point[], Rectangle, GraphicsUnit, ImageAttributes).

After median filter I want to apply binaryzation filter (for each pixel calculate brightness: B=0.299*R+0.5876*G+0.114B, if brightness less than thresholdValue (thresholdValue is parametr for my task in [0...255]) then value of my pixel in result image is 1, otherwise - 0) Speed in binaryzation filter is important for me too

A: 

Copy data to an array using CopyPixels, then operate on the array. Here is a code snippet where I take the average color:

int stride = (bmp.PixelWidth * bmp.Format.BitsPerPixel + 7) / 8;
byte[] pixels = new byte[bmp.PixelHeight * stride];
bmp.CopyPixels(pixels, stride, 0);
double[] averageComponents = new double[bmp.Format.BitsPerPixel / 8];

for (int pixel = 0; pixel < pixels.Length; pixel += averageComponents.Length)
{
    for (int component = 0; component < averageComponents.Length; component++)
    {
        averageComponents[component] += pixels[pixel + component];
    }
}

The filters you're using should run fast enough without any further optimizations (Just don't do something algorithmically slow).

CookieOfFortune
+7  A: 

Just found this link: A fast way to grayscale an image in .NET (C#)

/// <summary>
/// Grayscales a given image.
/// </summary>
/// <param name="image">
/// The image that is transformed to a grayscale image.
/// </param>
public static void GrayScaleImage(Bitmap image)
{
    if (image == null)
        throw new ArgumentNullException("image");

    // lock the bitmap.
    var data = image.LockBits(
                  new Rectangle(0, 0, image.Width, image.Height), 
                  ImageLockMode.ReadWrite, image.PixelFormat);
    try
    {
        unsafe
        {
            // get a pointer to the data.
            byte* ptr = (byte*)data.Scan0;

            // loop over all the data.
            for (int i = 0; i < data.Height; i++)
            {
                for (int j = 0; j < data.Width; j++)
                {
                    // calculate the gray value.
                    byte y = (byte)(
                        (0.299 * ptr[2]) + 
                        (0.587 * ptr[1]) + 
                        (0.114 * ptr[0]));

                    // set the gray value.
                    ptr[0] = ptr[1] = ptr[2] = y;

                    // increment the pointer.
                    ptr += 3;
                }

                // move on to the next line.
                ptr += data.Stride - data.Width * 3;
            }
        }
    }
    finally
    {
        // unlock the bits when done or when 
        // an exception has been thrown.
        image.UnlockBits(data);
    }
}

EDIT: See more info:

  1. Using the LockBits method to access image data
  2. GrayScale and ColorMatrix
Rubens Farias
A: 

If copying's too slow for you, use LockBits and an unsafe block to modify the resulting BitmapData structure directly.

David Seiler