Thursday, October 28, 2010

Comparing two Images

Few days back I was looking to compare two image and find difference between them in WPF. After searching and reading few articles I realized that comparing two image and find difference is much easier using methods of Graphics Class (i.e. using GDI+).  So I decide to compare and find difference between two images using GDI+ and then convert into a BitmapImage. For faster comparing we have to use pointer and write code in unsafe block. As pointer and unsafe block are not supported in VB.NET so comparing code has to be in C# or C++.

CompareImage1

CompareImage2

Code

public static Bitmap BitmapDifference(Bitmap first, Bitmap second)
{
BitmapData data1 = first.LockBits(new Rectangle(0, 0, first.Width, first.Height), ImageLockMode.ReadWrite, first.PixelFormat);
BitmapData data2 = second.LockBits(new Rectangle(0, 0, second.Width, second.Height), ImageLockMode.ReadWrite, second.PixelFormat);
Bitmap bmpresult = new Bitmap(first.Width, first.Height);

BitmapData data3 = bmpresult.LockBits(new Rectangle(0, 0, bmpresult.Width, bmpresult.Height), ImageLockMode.ReadWrite, first.PixelFormat);

unsafe
{
int remain1 = data1.Stride - data1.Width * 3;
int remain2 = data2.Stride - data2.Width * 3;
int remain3 = data3.Stride - data3.Width * 3;

byte* ptr1 = (byte*)data1.Scan0;
byte* ptr2 = (byte*)data2.Scan0;
byte* ptr3 = (byte*)data3.Scan0;

for (int i = 0; i < first.Height; i++)
{
for (int j = 0; j < first.Width * 3; j++)
{
byte ac = (byte)(Math.Abs(ptr1[0] - ptr2[0]));
if (ac < 15)
{
//Change Pixel Color to Black for all the pixel whose value is
ptr3[0] = 0;
}
else
{
ptr3[0] = ac;
}
ptr1++;
ptr2++;
ptr3++;
}
ptr1 += remain1;
ptr2 += remain2;
ptr3 += remain3;
}
}
first.UnlockBits(data1);
second.UnlockBits(data2);
bmpresult.UnlockBits(data3);

bmpresult.MakeTransparent(Color.Black);
return bmpresult;
}
Above function will return the difference between two images using following code 

public void GetDifference()
{
Bitmap bmp1 = new Bitmap(@"C:\1.jpg");
Bitmap bmp2 = new Bitmap(@"C:\2.jpg");
Bitmap result = BitmapDifference(bmp1, bmp2);
result.Save(@"C:\new.jpg");
}

Sunday, August 22, 2010

Sender Property of MailMessage

Many of the time we need to send email on behalf of someone else. For Example, all the employees in the company sending email on behalf of the company. Another common example is invitation email send to the friends by the website on behalf of its user. We have two properties available in MailMessage Class in .NET which are From and Sender which by definition looks very similar but they are different.

When sending a email From Property will contain the Email Address on behalf of whom we are sending the email and Sender property will be the person who is sending the email. Sender is an optional property and is used when we need to send email on behalf of someone else. When we are sending an email  which require authentication (i.e. Credentials) and our MailMessage has Sender property assigned, then Username of NetworkCredential will be same as Sender Email Address.  Below is the code of how we can use it.

Dim msg As New MailMessage
msg.From = New MailAddress("from@domain.com")
msg.Sender = New MailAddress("sender@domain.com")
msg.Subject = "Test Email"
msg.Body = "Hello World. This is a Test Email"

Dim client As New SmtpClient("Host Address", "Port Number")
client.Credentials = New NetworkCredential(msg.Sender.Address, "Password")
client.Send(msg)

Note: Although I have not tested on other SSL Enabled email provider but Sender Property doesn’t work with Gmail. So I think if Smtp Server requires SSL then Sender Property might not work.

Saturday, February 6, 2010

Print Multiple-layered column header in datagridview

Recently someone had asked a question on a forum of “How to create multiple-layered column header in datagridview and also have a print preview of it in vb.net”. Creating multiple-layered column header is available on “Windows Forms Data Controls and Data Binding Forum FAQ” on MSDN Forum but the code is provided in VC#. So I have created a code in VB.NET through which multiple-layered column header can be created as well we can have print preview of it.

Multiple-layered Column Header DatagridView

Datagridview1

To create a datagridview with multiple column header we have to handle the DataGridView.Painting and DataGridView.CellPainting events, so that we can draw header as we want. We can use PrintPage event of PrintDocument to build the page for printing.

Print Preview of Multi-layered Column Datagridview

Datagridview2

Code for Datagridview

Imports System.Drawing.Printing
Public Class DemoForm
Dim names() As String = {"Microsoft", "Adobe", "SUN"}
Dim WithEvents MyPrintDocument As New PrintDocument
Private Sub DemoForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.DataGridView1.Columns.Add("clmProduct1", "Product")
Me.DataGridView1.Columns.Add("clmPrice1", "Price")
Me.DataGridView1.Columns.Add("clmProduct2", "Product")
Me.DataGridView1.Columns.Add("clmPrice2", "Price")
Me.DataGridView1.Columns.Add("clmProduct3", "Product")
Me.DataGridView1.Columns.Add("clmPrice3", "Price")
DataGridView1.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.EnableResizing
DataGridView1.ColumnHeadersHeight = DataGridView1.ColumnHeadersHeight * 2
DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.BottomCenter
End Sub
Private Sub
DataGridView1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles DataGridView1.Paint
For i As Integer = 0 To 5 Step 2
Dim rec As Rectangle = DataGridView1.GetCellDisplayRectangle(i, -1, True)
rec.X += 1
rec.Y += 1
rec.Width = rec.Width * 2 - 2
rec.Height = rec.Height / 2 - 2
e.Graphics.FillRectangle(New SolidBrush(Me.DataGridView1.ColumnHeadersDefaultCellStyle.BackColor), rec)
Dim format As New StringFormat
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(names(i / 2), DataGridView1.ColumnHeadersDefaultCellStyle.Font, New SolidBrush(DataGridView1.ColumnHeadersDefaultCellStyle.ForeColor), rec, format)
Next
End Sub
Private Sub
DataGridView1_CellPainting(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellPaintingEventArgs) Handles DataGridView1.CellPainting
If e.RowIndex = -1 And e.ColumnIndex <> -1 Then
e.PaintBackground(e.CellBounds, False)
Dim rec As Rectangle = e.CellBounds
rec.Y += e.CellBounds.Height / 2
rec.Height = e.CellBounds.Height / 2
e.PaintContent(rec)
e.Handled = True
End If
End Sub

Private Sub
btnPrint_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPrint.Click
Dim dg As New PrintPreviewDialog
dg.Document = MyPrintDocument
dg.ShowDialog()
End Sub

Private Sub
PrintDocument1_PrintPage(ByVal sender As System.Object, ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles MyPrintDocument.PrintPage
Dim leftMargin As Integer = 10
Dim position As Integer = leftMargin
Dim yPosition As Integer
Dim
height As Integer = DataGridView1.ColumnHeadersHeight / 2
yPosition = 0
For i As Integer = 0 To 5 Step 2
Dim totalWidth As Double = DataGridView1.Columns(i).Width + DataGridView1.Columns(i + 1).Width
e.Graphics.FillRectangle(New SolidBrush(Color.LightGray), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, totalWidth, height))
Dim format As New StringFormat
format.Alignment = StringAlignment.Center
format.LineAlignment = StringAlignment.Center
e.Graphics.DrawString(names(i / 2), New Font("Arial", 12, FontStyle.Bold), Brushes.Black, position, yPosition)
position = position + totalWidth
Next

position = leftMargin
yPosition = DataGridView1.ColumnHeadersHeight / 2
For Each dr As DataGridViewColumn In DataGridView1.Columns
Dim totalWidth As Double = dr.Width
e.Graphics.FillRectangle(New SolidBrush(Color.LightGray), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawString(dr.HeaderText, New Font("Arial", 12, FontStyle.Bold), Brushes.Black, position, yPosition)
position = position + totalWidth
Next

For Each
dr As DataGridViewRow In DataGridView1.Rows
position = leftMargin
yPosition = yPosition + DataGridView1.ColumnHeadersHeight / 2
For Each dc As DataGridViewCell In dr.Cells
Dim totalWidth As Double = dc.OwningColumn.Width
e.Graphics.FillRectangle(New SolidBrush(Color.White), New Rectangle(position, yPosition, totalWidth, height))
e.Graphics.DrawRectangle(Pens.Black, New Rectangle(position, yPosition, dc.OwningColumn.Width, height))
e.Graphics.DrawString(dc.Value, New Font("Arial", 12, FontStyle.Regular), Brushes.Black, position, yPosition)
position = position + totalWidth
Next
Next
End Sub

End Class

Sunday, January 3, 2010

Gaurav Khanna – Microsoft MVP 2010

I am proud to announce that I am awarded Microsoft MVP on January 01, 2010 for providing technical expertise in Visual Basic technical communities for past one year.

About the MVP Award Program (As described by microsoft)

Since the early 1990s, Microsoft has recognized the inspiring activities of MVPs around the world with the MVP Award. MVPs freely share their deep knowledge, real-world experience, and impartial, objective feedback to help people enhance the way they use technology. Of more than 100 million users who participate in technology communities, around 4,000 are recognized as Microsoft MVPs.

MVPs make exceptional contributions to technical communities, sharing their passion, knowledge, and know-how. Meanwhile, because MVPs hear the opinions and needs of many others in the technical community, they are well-placed to share highly focused feedback with Microsoft.

MVPs are independent experts who are offered a close connection with people at Microsoft. To acknowledge MVPs’ leadership and provide a platform to help support their efforts, Microsoft often gives MVPs early access to Microsoft products, as well as the opportunity to pass on their highly targeted feedback and recommendations about product design, development, and support.

Email from Microsoft

Dear Gaurav Khanna,

Congratulations! We are pleased to present you with the 2010 Microsoft® MVP Award! This award is given to exceptional technical community leaders who actively share their high quality, real world expertise with others. We appreciate your outstanding contributions in Visual Basic technical communities during the past year.

The Microsoft MVP Award provides us the unique opportunity to celebrate and honor your significant contributions and say “Thank you for your technical leadership.”

Toby Richards
General Manager
Community & Online Support

List of MVPs announced from South Asia in January 2010 can be found on following link

http://blogs.technet.com/southasiamvp/archive/2010/01/03/new-mvps-announced-january-2010.aspx

Sunday, October 18, 2009

I’m A VB: Gaurav Khanna

My Interview with some of the great VB.NET programmer in MSDN Website. It great to be in the list with leading programmer of VB.NET.

http://blogs.msdn.com/vbteam/pages/i-m-a-vb-gaurav-khanna.aspx

Sunday, October 4, 2009

Encrypt/Decrypt Text in VB.NET

In this article I have code which can be used encrypt the text before saving it in the file, database, registry, etc to protect from misuse. There are many article we can find on internet to encrypt/decrypt text in .Net. Each have different ways for encryption with some having very long code. So I have created a  very simple two functions to encrypt/decrypt a text in .Net. Both the functions contains two parameter. First parameter “Text” will be the text which need to encrypted and second parameter is “Key” which is a private key which will help identity during decrypt. So key during decrypt should be same as in encypt to decrypt the text correctly.

Code to encrypt the Text

 

Imports System.Security.Cryptography
Imports System.Text
Imports System.IO

Function Encrypt(ByVal text As String, ByVal key As String) As String
Try
Dim crp As New TripleDESCryptoServiceProvider
Dim uEncode As New UnicodeEncoding
Dim bytPlainText() As Byte = uEncode.GetBytes(text)
Dim stmCipherText As New MemoryStream
Dim slt() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
Dim pdb As New Rfc2898DeriveBytes(key, slt)
Dim bytDerivedKey() As Byte = pdb.GetBytes(24)

crp.Key = bytDerivedKey
crp.IV = pdb.GetBytes(8)

Dim csEncrypted As New CryptoStream(stmCipherText, crp.CreateEncryptor(), CryptoStreamMode.Write)

csEncrypted.Write(bytPlainText, 0, bytPlainText.Length)
csEncrypted.FlushFinalBlock()
Return Convert.ToBase64String(stmCipherText.ToArray())
Catch ex As Exception
Throw
End Try
End Function

So for example Encrypt(“Demo”, “12345″) will return 1T5yxecmgLbsxQu4iQx5Bg==”


Code to decrypt the Text

Function Decrypt(ByVal text As String, ByVal key As String) As String
Dim crp As TripleDESCryptoServiceProvider
Try
crp = New TripleDESCryptoServiceProvider
Dim uEncode As New UnicodeEncoding
Dim bytCipherText() As Byte = Convert.FromBase64String(text)
Dim stmPlainText As New MemoryStream
Dim stmCipherText As New MemoryStream(bytCipherText)
Dim slt() As Byte = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
Dim pdb As New Rfc2898DeriveBytes(key, slt)
Dim bytDerivedKey() As Byte = pdb.GetBytes(24)
crp.Key = bytDerivedKey
crp.IV = pdb.GetBytes(8)

Dim csDecrypted As New CryptoStream(stmCipherText, crp.CreateDecryptor(), CryptoStreamMode.Read)
Dim sw As New StreamWriter(stmPlainText)
Dim sr As New StreamReader(csDecrypted)
sw.Write(sr.ReadToEnd)
sw.Flush()
csDecrypted.Clear()
crp.Clear()
Return uEncode.GetString(stmPlainText.ToArray())
Catch ex As Exception
Throw
End Try
End Function

So now when we decrypt the text encrypted above we will get the required text

So Decrypt(“1T5yxecmgLbsxQu4iQx5Bg==”, “12345″) will return “Demo”

Saturday, May 23, 2009

Send email with embedded Image

Recently one of my friend wanted to send email containing embedded image, similarly like we can do using Outlook. So I decided to create an example for him. To embed external resource in email we can use LinkedResource class provide in System.Net.Mail. In this article we will send email containing embedded image with smtp server as gmail.

Code:

Private Sub SendEmail()
Dim mail As New MailMessage("fromAddress@gmail.com", "toAddress@gmail.com")
mail.Subject = "This is an embedded image mail"
'create the image resource from image path using LinkedResource class..
Dim imageResource1 As New LinkedResource("C:\MyPhotos\Photo1.jpg", "image/jpeg")
imageResource1.ContentId = "uniqueId1"
imageResource1.TransferEncoding = TransferEncoding.Base64
Dim imageResource2 As New LinkedResource("C:\MyPhotos\Photo2.jpg", "image/jpeg")
imageResource2.ContentId = "uniqueId2"
imageResource2.TransferEncoding = TransferEncoding.Base64
Dim htmlBody As New StringBuilder
htmlBody.AppendLine("")
htmlBody.AppendLine("<b>LIST OF PHOTOS</b>")
htmlBody.AppendLine("</br></br>")
htmlBody.AppendLine("PHOTO 1")
htmlBody.AppendLine("<img alt="""" hspace=0 src=""cid:uniqueId1"" align=baseline border=0 >")
htmlBody.AppendLine("</br></br>")
htmlBody.AppendLine("PHOTO 2")
htmlBody.AppendLine("<img alt="""" hspace=0 src=""cid:uniqueId2"" align=baseline border=0 >")
htmlBody.AppendLine("</br></br>")
Dim htmlView As AlternateView = AlternateView.CreateAlternateViewFromString(htmlBody.ToString, Nothing, "text/html")
'adding the imaged linked to htmlView...
htmlView.LinkedResources.Add(imageResource1)
htmlView.LinkedResources.Add(imageResource2)
mail.AlternateViews.Add(htmlView)
Dim smtp As New SmtpClient("smtp.gmail.com", 587)
'If smtp server requires SSL
smtp.EnableSsl = True
smtp.Credentials = New NetworkCredential("fromAddress@gmail.com", "SMTP Password")
smtp.Send(mail)
End Sub