Sunday, November 27, 2011

Handling Images in C#

Image Handling in C#
An Image as we all know is a two dimensional array of pixels. Each pixel has three components Red, Green & Blue. However there is a bit of a surprise here. The first pixel is Blue,the second Green and the last Red. Pixels can be handled directly, however, processing gets very slow. Therefore we shall use pointers. to do this we must use unsafe code. The first requirement is to compile the application with the unsafe switch. Here is how it's done. Open the properties of the project and check the allow unsafe code check box.

First of all we should lock the bitmap using the LockBits method. This is done like this :-
BitmapData inputdata = inputbitmap.LockBits(new Rectangle(0, 0, inputbitmap.Width, inputbitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
Next we calculate the stride.The stride is the width of a single row of pixels (a scan line), rounded up to a four-byte boundary. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
int inputstride = inputdata.Stride;

Next we get the address of the first pixel in the bitmap.
System.IntPtr inputScan = inputdata.Scan0;
Next calculate the offset. This is done by 
int newOffset1 = inputstride - inputbitmap.Width * 3;
Now we are ready to implement a simple filter. This will simply interchange the Red and Green pixel values and create a new bitmap.
HypatiaFilters.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Imaging ;
using System.Drawing ;
namespace PictureFiltering
{
    public static class HypatiaFilters
    {
        public static Bitmap ExchangeRedAndGreen(Bitmap inputbitmap)
        {

            Bitmap outputbitmap = new Bitmap(inputbitmap.Width, inputbitmap.Height);

            BitmapData inputdata = inputbitmap.LockBits(new Rectangle(0, 0, inputbitmap.Width, inputbitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData outputdata = outputbitmap.LockBits(new Rectangle(0, 0, outputbitmap.Width, outputbitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            int inputstride = inputdata.Stride;
            int outputstride = outputdata.Stride;

            System.IntPtr inputScan = inputdata.Scan0;
            System.IntPtr outputScan = outputdata.Scan0;
            unsafe
            {

                byte* newp1 = (byte*)(void*)inputScan;
                byte* newp2 = (byte*)(void*)outputScan;

                int newOffset1 = inputstride - inputbitmap.Width * 3;
                int newOffset2 = outputstride - outputdata.Width * 3;

                byte redvalue, greenvalue, bluevalue;
                byte newred, newgreen, newblue;
                for (int y = 0; y < inputbitmap.Height; ++y)
                {
                    for (int x = 0; x < inputbitmap.Width; ++x)
                    {


                        bluevalue = newp1[0];
                        greenvalue = newp1[1];
                        redvalue = newp1[2];

                        newblue  = bluevalue ;
                        newgreen  = redvalue ;
                        newred  = greenvalue ;

                        newp2[0] = newblue ;
                        newp2[1] = newgreen ;
                        newp2[2] = newred ;
                        newp1 += 3;
                        newp2 += 3;
                    }

                    newp1 += newOffset1;
                    newp2 += newOffset2;
                }
            }


            inputbitmap.UnlockBits(inputdata );
            outputbitmap.UnlockBits(outputdata );
            return outputbitmap;



        }
    }
}
Here is a result of a run of this software

I have put all this in a windows application



Form1.Designer.cs


namespace PictureFiltering
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.p1 = new System.Windows.Forms.PictureBox();
            this.button1 = new System.Windows.Forms.Button();
            this.ofd = new System.Windows.Forms.OpenFileDialog();
            this.p2 = new System.Windows.Forms.PictureBox();
            ((System.ComponentModel.ISupportInitialize)(this.p1)).BeginInit();
            ((System.ComponentModel.ISupportInitialize)(this.p2)).BeginInit();
            this.SuspendLayout();
            //
            // p1
            //
            this.p1.Location = new System.Drawing.Point(32, 12);
            this.p1.Name = "p1";
            this.p1.Size = new System.Drawing.Size(420, 380);
            this.p1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.p1.TabIndex = 0;
            this.p1.TabStop = false;
            //
            // button1
            //
            this.button1.Location = new System.Drawing.Point(538, 410);
            this.button1.Name = "button1";
            this.button1.Size = new System.Drawing.Size(75, 23);
            this.button1.TabIndex = 1;
            this.button1.Text = "Get Image";
            this.button1.UseVisualStyleBackColor = true;
            this.button1.Click += new System.EventHandler(this.button1_Click);
            //
            // ofd
            //
            this.ofd.FileOk += new System.ComponentModel.CancelEventHandler(this.ofd_FileOk);
            //
            // p2
            //
            this.p2.Location = new System.Drawing.Point(636, 12);
            this.p2.Name = "p2";
            this.p2.Size = new System.Drawing.Size(420, 380);
            this.p2.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
            this.p2.TabIndex = 0;
            this.p2.TabStop = false;
            //
            // Form1
            //
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1107, 474);
            this.Controls.Add(this.button1);
            this.Controls.Add(this.p2);
            this.Controls.Add(this.p1);
            this.Name = "Form1";
            this.Text = "Hypatia Picture Filtering";
            ((System.ComponentModel.ISupportInitialize)(this.p1)).EndInit();
            ((System.ComponentModel.ISupportInitialize)(this.p2)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.PictureBox p1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.OpenFileDialog ofd;
        private System.Windows.Forms.PictureBox p2;
    }
}







Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace PictureFiltering
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            ofd.ShowDialog(this);
        }

        private void ofd_FileOk(object sender, CancelEventArgs e)
        {
            p1.Image = System.Drawing.Image.FromFile(ofd.FileName);
            p2.Image = HypatiaFilters.ExchangeRedAndGreen((Bitmap)p1.Image);
           
        }
    }
}
 

Program.cs 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace PictureFiltering
{
    static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

No comments:

Post a Comment