Wednesday, June 18, 2014

Image Processing in .NET

.Net provides the core for Faster Image Processing using System.Drawing assembly and System.Drawing namespace.

 

Basic About Image

Raster Images are consists of Rows and Columns of Pixels.

A Pixel consists of bytes of values for Pixel

A pixel with 4 bytes usually consists of Alpha, Red, Green and Blue values

A pixel with 3 bytes usually consists of Red, Green and Blue values

A pixel with less than 3 bytes needs further processing like expansion or look up to built 3/4 byte Pixel

 

Steps for Image Processing

Load the Image file into Memory

System.Drawing.Image and System.Drawing.Bitmap classes can be used for loading Images into Memory

System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filename);

Getting Pixel Data

BitmapData helps to get the pixel data to Memory and we can use Marshal helper class to load the pixel data into byte array.

var bitmapData = bmp.LockBits(
  new Rectangle(0, 0, bmp.Width, bmp.Height),  // Take all the bytes
  System.Drawing.Imaging.ImageLockMode.ReadWrite,
  System.Drawing.Imaging.PixelFormat.Format24bppRgb); // 3 byte Colors

// Copy Pixel data to Byte Array for Faster processing

var pixelBytes = new byte[bitmapData.Height * bitmapData.Stride]; // Total size to read the data

System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, pixelBytes, 0, pixelBytes.Length);

 

Do the manipulation on the Byte Array

There are so many concepts, calculations and algorithms available for doing the Image processing like color to gray scale conversion, blurring, sharpening etc. You can apply one or more on the entire image or a portion of an image.

Save the changes back to Bitmap

It is just the reverse process of the getting pixel data

System.Runtime.InteropServices.Marshal.Copy(pixelBytes, 0, bitmapData.Scan0, pixelBytes.Length);
bmp.UnlockBits(bitmapData);

Example

public static void ToGrayScale(string filename, string newfilename) {
    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(filename);
    ToGrayScale(bmp);
    bmp.Save(newfilename);
}

public static void ToGrayScale(System.Drawing.Bitmap bmp) {
    var bitmapData = bmp.LockBits(
            new Rectangle(0, 0, bmp.Width, bmp.Height),  // Take all the bytes
            System.Drawing.Imaging.ImageLockMode.ReadWrite,
            System.Drawing.Imaging.PixelFormat.Format24bppRgb); // 3 byte Colors

    // Copy Pixel data to Byte Array for Faster processing
    var pixelBytes = new byte[bitmapData.Height * bitmapData.Stride]; // Total size to read the data
    System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, pixelBytes, 0, pixelBytes.Length);
    for (var y = 0; y < bmp.Height; y++) {
        var st = y * bitmapData.Stride;
        for (var x = 0; x < bmp.Width; x++) {
            var p = st + x * 3;
            var r = pixelBytes[p];
            var g = pixelBytes[p + 1];
            var b = pixelBytes[p + 2];

            // Do your processing here
            var n = (byte)(r * .22 + g * .66 + b * .12);

            pixelBytes[p] = r;
            pixelBytes[p + 1] = b;
            pixelBytes[p + 2] = g;
        }
    }

    // Update it back to bitmap data
    System.Runtime.InteropServices.Marshal.Copy(pixelBytes, 0, bitmapData.Scan0, pixelBytes.Length);
    bmp.UnlockBits(bitmapData);
}

No comments:

Post a Comment