It’s not often I post something seriously techie, but when I discovered the answer to a problem, I originally posted on StackOverflow, I thought it would be good to not only answer it there, but to offer a little more depth here.
One of the hats I wear is a programmer, more specifically a programmer for desktop, web and mobile/hand held applications. One type of system I develop is Proof of Delivery (POD), where the hand held is used to capture the consignees signature. I’ve done this before using the OpenNetCF Signature component, converting the signature on the hand held to bitmap and then sending it back to the server when the hand held is docked to the desktop machine. The system I was recently working on however worked in wireless mode across a wide area network, so the thought of sending hundreds of bitmaps across the network, wasn’t something I relished.
I remembered that the native format for the signature was vector based. This means that instead of storing every individual pixel, the signature is stored as lines between two points, which is much more efficient. To give you an idea, the raw windows bitmap, averaged out at around 35K, while the vector version is between 200 and 1000 bytes, or 1K. As you can see this is quite a saving. I decided for this project to store the vectors as is, thinking I would make use of them on the server when the time arrived. Unfortunately when the time came around, there was seemingly no way to convert this vector format, back to a bitmap, as the OpenNetCF library was only for Windows Mobile. I did have a fall back plan, but was hoping not to use it, should the conversion not be possible, which it nearly wasn’t.
This though didn’t stop me adding a reference to the OpenNetCF libraries in my ASP.NET project and trying to use the signature control to go from the vector format back to a bitmap. While this seemingly appeared to be possible, when push came to shove, I kept getting an error saying the vector size was different to the signature size I was specifying, even though I was coping the size specified on the hand held. I think I may have a solution to that problem, but thankfully I didn’t need to go that route.
This lead me to do some Googling and after many dead ends, I finally found a post on the OpenNetCF forum, which appeared to be an answer to my prayers. The only two problems were that the solution was based on version 1.4 of the framework and I was using 2.1, and the sample source code was in C#, and I’m predominately a VB.NET programmer. I decided to convert the source anyway, which really wasn’t that bad. And I ended up with something that worked great and didn’t require me to use the OpenNetCF libraries on the desktop. This solution works fine and has been used for version 2.1, but should work unchanged for version 2.0 and 1.4.
Many thanks to this anonymous poster, on the OpenNetCF forums. Here’s the code:
Dim pic As System.Windows.Forms.PictureBox
Dim word As Integer
Dim lngIndex As Integer
Dim lngPointsToRead As Integer = 0
Dim lngCurrX As Integer = -1
Dim lngCurrY As Integer = -1
Dim lngPrevX As Integer = -1
Dim lngPrevY As Integer = -1
Dim lngWidth As Integer = 1
Dim lngHeight As Integer
Dim bit As New System.Drawing.Bitmap(1, 1)
Dim g As Graphics = Graphics.FromImage(bit)
pic = New picturebox()
Dim blackpen As New Pen(Color.Black)
If arrsig.Length < 3 Then
Return Nothing
End If
word = arrsig(0)
word = word + System.Convert.ToInt32(arrsig(1)) * 256
lngWidth = word
word = arrsig(2)
word = word + System.Convert.ToInt32(arrsig(3)) * 256
lngHeight = word
bit = New Bitmap(lngWidth, lngHeight)
g = Graphics.FromImage(bit)
g.Clear(backcolor)
lngIndex = 4
While (True)
If (lngIndex >= arrsig.Length) Then
Exit While
End If
If (lngPointsToRead = 0) Then
word = arrsig(lngIndex)
lngIndex = lngIndex + 1
word = word + System.Convert.ToInt32(arrsig(lngIndex)) * 256
lngPointsToRead = word
lngPrevX = -1
lngPrevY = -1
Else
If (lngCurrX = -1) Then
word = arrsig(lngIndex)
If (lngWidth > 255) Then
lngIndex = lngIndex + 1
word = word + System.Convert.ToInt32(arrsig(lngIndex)) * 256
End If
lngCurrX = word
ElseIf (lngCurrY = -1) Then
word = arrsig(lngIndex)
If (lngHeight > 255) Then
lngIndex = lngIndex + 1
word = word + System.Convert.ToInt32(arrsig(lngIndex)) * 256
End If
lngCurrY = word
lngPointsToRead = lngPointsToRead - 1
If (lngPrevX <> -1) Then
g.DrawLine(blackpen, lngPrevX, lngPrevY, lngCurrX, lngCurrY)
End If
lngPrevX = lngCurrX
lngPrevY = lngCurrY
lngCurrX = -1
lngCurrY = -1
End If
End If
lngIndex = lngIndex + 1
End While
pic.Image = bit
Return pic.Image
End Function
I’d love to hear if you make use of this code, but it comes with no guarantees or warranties, so use at your own risk.