Monday, November 28, 2011

Image Filters

This is a continuation of the previous post at Handling Images in C#
A Grayscale Filter
To develop a Grayscale filter simply add up the red green and blue pixels and divide by 3. This averages out the values.

public static Bitmap GrayScaleFilter(Bitmap inputbitmap)
        {

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

            BitmapData inputdata = inputbitmap.LockBits(new Rectangle(0, 0, inputbitmap.Width, inputbitmap.Height), ImageLockMode.ReadOnly, 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];
                        byte  grayscalevalue =(byte )( (redvalue + greenvalue + bluevalue) / 3.0);
                       

                        newp2[0] = grayscalevalue  ;
                        newp2[1] = grayscalevalue  ;
                        newp2[2] = grayscalevalue  ;
                        newp1 += 3;
                        newp2 += 3;
                    }

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


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



        }




A BlackAndWhite Filter

Simply take the averaged value from the previous filter. If the average is greater than 128 make it white 255 else make it black 255.


      public static Bitmap BlackAndWhiteFilter(Bitmap inputbitmap)
        {

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

            BitmapData inputdata = inputbitmap.LockBits(new Rectangle(0, 0, inputbitmap.Width, inputbitmap.Height), ImageLockMode.ReadOnly, 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;
              
                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];
                        byte  avgvalue =(byte )( (redvalue + greenvalue + bluevalue) / 3.0);
                        if (avgvalue > 128)
                            avgvalue = 255;
                        else
                            avgvalue = 0;

                        newp2[0] = avgvalue   ;
                        newp2[1] = avgvalue   ;
                        newp2[2] = avgvalue   ;
                        newp1 += 3;
                        newp2 += 3;
                    }

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


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



        }


Next we shall develop edge detection filters.

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());
        }
    }
}

Saturday, November 26, 2011

A Basic Android Example

A Basic Android Example
Android according to the definition provided at developer.android.com is 
 a software stack for mobile devices that includes an operating system, middleware and key applications. The Android SDK provides the tools and APIs necessary to begin developing applications on the Android platform using the Java programming language.

It provides the necessary tools for developing software for the Android OS. Important parts are :-
1) SQLLite for Data Storage.
2) Optimized Graphics 
3) Media support for common audio/video formats & still image formats.
4) GSM
5) Bluetooth
6) Camera, GPS , etc,

For developing Android applications we need to download the Android SDK, and also setup Eclipse on our computer. Both are available as free downloads. It is also possible to develop using only the Android SDK from the commandline.

Many setup guides are available on the internet, and setting up the environment should be a cinch.

A Sample Application
To begin, let us develop a simple application that shall read two numbers from two textfields and display their sum in the third.

First of all start Eclipse, New Project  and select Android Project.
Since we are developing for the Samsung Galaxy, select Samsung Tab.

Android programming is done using the Java Programming Language, and user interface design is done using XML. 
To create the user interface .
After creating the project.

Open main.xml
This will bring up the User Interface designer. It has two views. The Graphical Layout & the XML view
Now we shall drag and drop three EditText boxes and a Button onto the mobile.
This is the user interface now.

This is the main.xml file

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/hello" />

    <EditText
        android:id="@+id/editText1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberSigned" >

        <requestFocus />
    </EditText>

    <EditText
        android:id="@+id/editText2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberSigned" />


    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Button" />

    <EditText
        android:id="@+id/editText3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberSigned" />

</LinearLayout>


We shall change the caption of the button to add.
This is done by adding a new String to
strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="hello">Dedicated to Hypatia of Alexandria</string>
    <string name="app_name">HypatiaBasicAndroid</string>
    <string name="buttoncaption">Add</string>

</resources>




 HypatiaBasicAndroidActivity.java
package hypatia.basic;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class HypatiaBasicAndroidActivity extends Activity {
    /** Called when the activity is first created. */
    EditText t1,t2,t3;
    Button b;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        b=(Button)findViewById(R.id.button1);
        t1=(EditText)findViewById(R.id.editText1);
        t2=(EditText)findViewById(R.id.editText2);
        t3=(EditText)findViewById(R.id.editText3);
       
        b.setOnClickListener(new ButtonHandler());
       
       
    }
    class ButtonHandler implements OnClickListener
    {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            try
            {
                int a=Integer.parseInt("" + t1.getText());
                int b=Integer.parseInt("" + t2.getText());
                int sum=a+b;
                t3.setText("" + sum);
               
            }
            catch (Exception ex) {
                // TODO: handle exception
                t3.setText(ex.getMessage());
            }
            }
        }
       
    }

In future posts, we shall cover all of android.