Monday, January 26, 2009

Digital Image processing in C#, and C++

I have been working on some image processing projects. I prepared two versions of image processing software in C#, and C++. There are a lot of functions and tools which if you want to get familiar to the mathematical formulas please check “Digital Image Processing, Second Edition – Rafael C.Gonzalez, Richard E.Woods”. The C++ version is much faster than the C# version, but you can only open and save BMP files with that whereas you can open different file formats using Bitmap class in C# and convert them to other formats too. In C# version you can open the file using the openfiledialog and then you need to copy the image from the original window to the working window and then apply the filters.











In C++ version pass the name of the image as an argument, and after the image is opened copy that to the source window, right click and from the popup menu apply the filter you want.


















There are some more functions in C++ that I will add them soon in future to the C# version.

In order to use C++ version you need to copy OpenGL files to your computer.

I will provide more details about the functions in future posts.

Saturday, January 17, 2009

Sending Files using TCP

A socket is an abstraction through which an application may send and receive data, in pretty much the same way as opening a file to read and write data. Different types of sockets correspond to different protocols. I will give you a brief description of TCP/IP protocol which has the main types of stream sockets and datagram sockets. Stream sockets use TCP and datagram sockets use UDP.

The .NET framework has two classes for TCP which are TCPClient and TCPListener. A TCPClient initiates the communication with a server which is waiting for the connection. TCP is connection oriented and UDP is connectionless, which means that UDP sockets do not need to be connected before being used. Another difference between TCP and UDP is that there is no guarantee that a message sent via a UDP socket will arrive at its destination, and messages can be delivered in a different order than they were sent.

You have to carefully choose when you want to use TCP and when UDP. When you are sending small amount of data, using TCP might double number of messages being sent and UDP provides minimal overhead platform.

Here I am going to show you a server/client application, which you can send files using TCP (I also talked about sending data using UDP here).

















Let’s talk about the client application first. The client application is consists of an OpenFileDialog for selecting the file you want to send, two text boxes to enter server IP address and server port number, A label which show you the status of your application such as connected to the server or number of bytes that have been sent, a progress bar, and a button named send which sends data to the server.

When you are connected via TCP you create a network stream which you can read and write in it similar to all other streams you worked with. Writing a large amount of data to the stream is not a good idea, so I break the selected file into smaller packets which each packet length is 1024 bytes (1KB) and then send all the packets to the server. The SendTCP function is as follows.


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.IO;

using System.Net;

using System.Net.Sockets;

namespace SendFiles

{

public partial class Form1 : Form

{

public string SendingFilePath = string.Empty;

private const int BufferSize = 1024;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

progressBar1.Visible=true;

progressBar1.Minimum=1;

progressBar1.Value=1;

progressBar1.Step=1;

}

private void btnBrowse_Click(object sender, EventArgs e)

{

OpenFileDialog Dlg = new OpenFileDialog();

Dlg.Filter = "All Files (*.*)|*.*";

Dlg.CheckFileExists = true;

Dlg.Title = "Choose a File";

Dlg.InitialDirectory = @"C:\";

if (Dlg.ShowDialog() == DialogResult.OK)

{

SendingFilePath = Dlg.FileName;

}

}

private void btnSend_Click(object sender, EventArgs e)

{

if (SendingFilePath != string.Empty)

{

SendTCP(SendingFilePath, txtIP.Text, Int32.Parse(txtPort.Text));

}

else

MessageBox.Show("Select a file","Warning");

}

public void SendTCP(string M, string IPA, Int32 PortN)

{

byte[] SendingBuffer = null;

TcpClient client = null;

lblStatus.Text = "";

NetworkStream netstream = null;

try

{

client = new TcpClient(IPA, PortN);

lblStatus.Text = "Connected to the Server...\n";

netstream = client.GetStream();

FileStream Fs = new FileStream(M, FileMode.Open, FileAccess.Read);

int NoOfPackets = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(Fs.Length) / Convert.ToDouble(BufferSize)));

progressBar1.Maximum = NoOfPackets;

int TotalLength = (int)Fs.Length, CurrentPacketLength, counter = 0;

for (int i = 0; i <>

{

if (TotalLength > BufferSize)

{

CurrentPacketLength = BufferSize;

TotalLength = TotalLength - CurrentPacketLength;

}

else

CurrentPacketLength = TotalLength;

SendingBuffer = new byte[CurrentPacketLength];

Fs.Read(SendingBuffer, 0, CurrentPacketLength);

netstream.Write(SendingBuffer, 0, (int)SendingBuffer.Length);

if (progressBar1.Value >= progressBar1.Maximum)

progressBar1.Value = progressBar1.Minimum;

progressBar1.PerformStep();

}

lblStatus.Text=lblStatus.Text+"Sent "+Fs.Length.ToString()+" bytes to the server";

Fs.Close();

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

finally

{

netstream.Close();

client.Close();

}

}

}

}


As you can see a TCP client and a network stream are being constructed and a network connection is initiated. After opening the selected file according to the buffer size which is 1024 bytes, number of packets that are going to be sent is calculated. There are two other variables CurrentPacketLength and TotalLength, if the total length of the selected file is more than the buffer size the CurrentPacketLength is set to the buffer size, otherwise why send some empty bytes, so CurrentPacketLength is set to the total length of the file. After that I subtract the current from the total length, so actually we can say total length is showing the total amount of data that has not been sent yet. The rest is pretty much straight forward, reading the data from the file stream and writing it to the SendingBuffer according to the CurrentPacketLength and writing the buffer to the network stream. After all packets have been sent, the status will show the amount of bytes you have sent to the server.








using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Net;

using System.Net.Sockets;

using System.IO;

using System.Threading;

namespace ReceiveFiles

{

public partial class Form1 : Form

{

private const int BufferSize = 1024;

public string Status = string.Empty;

public Thread T = null;

public Form1()

{

InitializeComponent();

}

private void Form1_Load(object sender, EventArgs e)

{

label1.Text = "Server is Running...";

ThreadStart Ts = new ThreadStart(StartReceiving);

T = new Thread(Ts);

T.Start();

}

public void StartReceiving()

{

ReceiveTCP(29250);

}

public void ReceiveTCP(int portN)

{

TcpListener Listener = null;

try

{

Listener = new TcpListener(IPAddress.Any, portN);

Listener.Start();

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

}

byte[] RecData = new byte[BufferSize];

int RecBytes;

for (; ; )

{

TcpClient client = null;

NetworkStream netstream = null;

Status = string.Empty;

try

{

string message = "Accept the Incoming File ";

string caption = "Incoming Connection";

MessageBoxButtons buttons = MessageBoxButtons.YesNo;

DialogResult result;

if (Listener.Pending())

{

client = Listener.AcceptTcpClient();

netstream = client.GetStream();

Status = "Connected to a client\n";

result = MessageBox.Show(message, caption, buttons);

if (result == System.Windows.Forms.DialogResult.Yes)

{

string SaveFileName=string.Empty;

SaveFileDialog DialogSave = new SaveFileDialog();

DialogSave.Filter = "All files (*.*)|*.*";

DialogSave.RestoreDirectory = true;

DialogSave.Title = "Where do you want to save the file?";

DialogSave.InitialDirectory = @"C:/";

if (DialogSave.ShowDialog() == DialogResult.OK)

SaveFileName = DialogSave.FileName;

if (SaveFileName != string.Empty)

{

int totalrecbytes = 0;

FileStream Fs = new FileStream(SaveFileName, FileMode.OpenOrCreate, FileAccess.Write);

while ((RecBytes = netstream.Read(RecData, 0, RecData.Length)) > 0)

{

Fs.Write(RecData, 0, RecBytes);

totalrecbytes += RecBytes;

}

Fs.Close();

}

netstream.Close();

client.Close();

}

}

}

catch (Exception ex)

{

Console.WriteLine(ex.Message);

//netstream.Close();

}

}

}

private void btnExit_Click(object sender, EventArgs e)

{

T.Abort();

this.Close();

}

}

}


A TCP listener is created and starts listening to the specified port. Again the buffer size is set to 1024 bytes. A TCP listener can pre check to see if there any connections pending before calling the AcceptTcpClient method. It returns true of there are any pending connections. This method is a good way of avoiding the socket being blocked. Before reading anything from the network stream a message box asks you if you want to accept the incoming connection, then a SaveFileDialog will be opened, and when you enter the file name plus extension, a file stream will be constructed and you start reading from the network stream and writing to the file stream. Create a thread in your code and run the receiving method in the created thread. I have sent more than 100 Mb files in a LAN with the application.


Wednesday, January 14, 2009

Creating a Windows Service for Watching System Directory's Files

I am going to explain the steps for creating a windows service which monitors some folders or files and write their changes in the event log. Creating services enables you to run an assembly in the background. Services are suitable for the times when you need to continuously listen to incoming network connections, or monitor something, or launch an assembly before the user logs in. Services can run automatically when the computer starts. When you compile the service project you need to install it so it could run on the server. You have to create an installation component for that which installs and registers the service on the server. You need to call Run method from the main method, so the service would be loaded into the Service Control Manager. We want to create a windows service which is able to monitor some files and report the changes, so we divide this post into 3 sections, which are Monitoring files, event log, and creating and installing windows services.

Monitoring Directories and Files:

FileSystemWatcher Class provides methods for monitoring files. The most important FileSystemWatcher events which you can register are:

  • Changed: Occurs when a file or directory has changed in the watched directory.
  • Created: Occurs when a file or directory has been created in the watched directory.
  • Deleted: Occurs when a file or directory has been deleted in the watched directory.
  • Renamed: Occurs when a file or directory has been renamed in the watched directory.

Let’s say you want to monitor all files in your windows directory, in system32 (C:\Windows\System32). The code is pretty much simple.

using System;

using System.IO;

using System.Text;

namespace ConsoleApplication3

{

class Program

{

static void Main(string[] args)

{

FileSystemWatcher Watcher = new FileSystemWatcher();

Watcher.Path = Environment.SystemDirectory;

Watcher.IncludeSubdirectories = true;

Watcher.Created += new FileSystemEventHandler(Wathcer_Changed);

Watcher.Deleted += new FileSystemEventHandler(Wathcer_Changed);

Watcher.EnableRaisingEvents = true;

Console.ReadLine();

}

static void Wathcer_Changed(object sender, FileSystemEventArgs e)

{

Console.WriteLine("Change Type = {0}, Path = {1}", e.ChangeType, e.FullPath);

}

}

}

You can either pass the path as an argument to the constructor of FileSystemWatcher or assign it to path properties. There is a property called IncludeSubdirectories which you can set to true and as you realize from the name it enables the watcher to watch sub directories too. There are two events Created and Deleted registered, which when ever they occur, the function Wathcer_Changed will be called and in that function the event type and the full path of the changed object will be displayed on the screen.

Event Log:

.NET framework has a class called EvenLog which you can create an event log using it. You have to use System.Diagnostics namespace. You can view event log by opening control panel and then Administrative tools, click on Event Viewer.














Using the following code you can create an event log TestLog and write an entry in that event log.

static void Main(string[] args)

{

if(!EventLog.SourceExists("TestLog","."))

EventLog.CreateEventSource("TestLog","Application");

EventLog Lg=new EventLog("Application",".","TestLog");

Lg.WriteEntry("The first test log",EventLogEntryType.Information);

Console.ReadLine();

}

You have two options for reading the event entry, either by opening the event viewer and then opening the application and click on the event you created and view the entry:













Or you can use this code to read the event entry:

static void Main(string[] args)

{

EventLog El = new EventLog("Application", ".", "TestLog");

foreach (EventLogEntry E in El.Entries)

{

if(E.Source=="TestLog")

Console.WriteLine(E.Source + " , " + E.Message);

}

Console.ReadLine();

}

Windows Services:

For creating a service project, click on file, new project and then select Windows Service.















Use the designer view, and from properties change the name and the service name to what ever name you like. You can also set CanPauseAndContinue and CanShutDown properties to true, so you would be able to pause, restart and shut down the service. Within the service class, add the code to OnStart, OnStop, OnPause, OnContinue, and OnShutdown methods.

protected override void OnStart(string[] args)

{

// TODO: Add code here to start your service.

FileSystemWatcher Watcher = new FileSystemWatcher();

Watcher.Path = Environment.SystemDirectory;

Watcher.IncludeSubdirectories = true;

Watcher.Created += new FileSystemEventHandler(Wathcer_Changed);

Watcher.Deleted += new FileSystemEventHandler(Wathcer_Changed);

Watcher.EnableRaisingEvents = true;

}

static void Wathcer_Changed(object sender, FileSystemEventArgs e)

{

if (!EventLog.SourceExists("TestLog", "."))

EventLog.CreateEventSource("TestLog", "Application");

EventLog Lg = new EventLog("Application", ".", "TestLog");

string Message = "The Changed File" + e.Name + " , " + e.FullPath;

Lg.WriteEntry(Message, EventLogEntryType.Information);

}

Now we have to create an installer for the service. In order to add an installer to the project you have to open the design view for the service, right click the designer and click Add Installer. Change the StartType property for the ServiceInstaller to Automatic. The StartType property can have one of the following values:

  • Automatic: The service starts automatically after the computer starts, whether or not a user logs in.
  • Manual: A user must manually start the service.
  • Disabled: The service does not start automatically and users can not start the service.

Set the Description property to “Logs file changes in the system directory” and set the DisplayName property to “System File Watcher”.

Select ServiceProcessInstaller component from the designer view.







Set the Account property to LocalSystem. Account property gets one of the following values according to the security context you want to specify for your service:

  • LocalService: As a non - privileged user on the local computer. Use this to minimize security risk.
  • NetworkService: Enables the service to authenticate to another computer on the network.
  • LocalSystem: As unlimited privileged user. It can cause a severe security risk if vulnerabilities in your service could be exploited to harm the computer data.
  • User: Causes the system to prompt for a valid user name and password.

Now you have to define your service startup object by right clicking the project in the solution explorer and choosing property. In the project designer, under application tab, select your service as the startup object.















You have to add a setup project to your service project in order to create a windows installer (MSI) package. Click on File, Add, New project and add a setup project to your solution.















You have to add the output from your service project to the setup project. Right click the setup project in the solution explorer, click Add, and then Project Output.


















From the Add output project dialog, select your service project from the list, and then select Primary Output.





















Add a custom action to install the service executable file. Right click the setup project in the solution explorer, click view, and then Custom Actions, and then right click the Custom Actions in the designer view and Click Add Custom Action.





























In the select Item Project dialog box, Select the Application Folder, and then select the Primary Output From the service.









The primary output will be added to the custom actions Install, Commit, Rollback and Uninstall.












Right click the setup project in the solution explorer and select Build. Go to your project’s folder, there will be a Setup.exe which is for installing the service. You can start, stop or change the Startup Type of your process, you can either go to control panel, Administrative Tools, Computer Management and the under Services and Application, click on Services and find your service or directly select Services in Administrative tools, and find your service.
















You can start the service by restarting your computer or by right clicking the service and select Start. Go to Windows/System32 folder and create a text file after you have started the service. Then return to services page and right click the service and stop it. Under the administrative tools, select Event Viewer, under applications, you can see the event entry which your service has entered.