Link to home
Start Free TrialLog in
Avatar of CISS
CISSFlag for United States of America

asked on

VB.Net how to convert memory stream into jpg on compact framework

I’m using some code that I got off dev buzz to capture a signature in a windows mobile application. I need to be able to save the data to a local sqlce database and post it via a web service so I can display the signature on packing list. The datatype on the database field is image. Currently the raw data is being stored into the database but I would like to convert it into a jpg prior to storing it in the database. How do I convert “stream” into a jpg prior to the save?

           Dim stream As System.IO.MemoryStream = _
     New System.IO.MemoryStream(_signature.SignatureBits)
            Dim sigLength As Int32 = CInt(stream.Length)

                  Dim strsql As String = String.Empty

                  If Not bRunOnce Then

                        strsql = "insert into Signatures (ID, DateCreated, Signature) VALUES (@ID, GetDate(), @Signature)"

                        bRunOnce = True

                  Else

                        strsql = "update Signatures set DateCreated = getdate(), Signature = @Signature where ID = @ID"

                  End If

                  Dim myCommand As New SqlCeCommand(strsql, myConn)
                  Dim param As SqlCeParameter = Nothing

                  param = New SqlCeParameter("@ID", Data.SqlDbType.Int)
                  myCommand.Parameters.Add(param)
                  myCommand.Parameters("@ID").Size = 4
                  myCommand.Parameters("@ID").Value = 1

                  If sigLength = 0 Then

                        param = New SqlCeParameter("@Signature", Data.SqlDbType.Image)
                        myCommand.Parameters.Add(param)
                        myCommand.Parameters("@Signature").Size = 0
                        myCommand.Parameters("@Signature").Value = DBNull.Value

                  Else

                        param = New SqlCeParameter("@Signature", Data.SqlDbType.Image)
                        myCommand.Parameters.Add(param)
                        myCommand.Parameters("@Signature").Size = stream.ToArray().Length
                        myCommand.Parameters("@Signature").Value = stream.ToArray()

                  End If

                  myCommand.ExecuteNonQuery()

                  sbar.Text = "Signature saved!"

            Catch ex As Exception

                  sbar.Text = "Signature did not save!"

                  MsgBox("Error: " & ex.Message)

            Finally

Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

You can use bitmap

Dim bmp As New Bitmap(stream)
Avatar of CISS

ASKER

I tried that but it throws the following exception

ex.Message      "Value does not fall within the expected range."      String

Here's my code
            Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits)
            Try
                bmp = New Bitmap(stream)
            Catch ex As Exception
                Dim s_message As String = ex.Message
            Finally
           
            End Try
Try changing

Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits)

to

Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits.ToArray)
Avatar of CISS

ASKER

SignatureBits Method returns Byte. When I try .ToArray I get the following exception
value of type '1-demensional array of byte' cannot be converted to 'system.io.memorystream'

Public ReadOnly Property SignatureBits() As Byte()
            Get
                  Return SignatureData.GetBytes(Me.Width, Me.Height, _lines)
            End Get
      End Property
Oh its a byte array already.

> "Value does not fall within the expected range."
Which line produces the error?
Avatar of CISS

ASKER

Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits).ToArray() Intellisense highlights the line and provides the feed back
I was talking about this error

> "Value does not fall within the expected range."

with
Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits)

And by the way, my suggestion was

Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits.ToArray())

and NOT

Dim stream As System.IO.MemoryStream = New System.IO.MemoryStream(_signature.SignatureBits).ToArray()
in that devbuzz example, _signature.SignatureBits is a property returning Byte(), so it IS already an array :)

I used that sample but in c#. In case of VB.NET, it's possible that it handles large numbers incorrectly unlike c#.

Try

stream.Read(_signature.SignatureBits,0,_signature.SignatureBits.Length)

instead, or even read it in a loop (1 byte at time) to see when it fails.
Avatar of CISS

ASKER

Getting closer doesn't throw an error but only produces a black jpg.
 Dim bmp As New Bitmap(200, 100)
        path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName)
            Try
            path += "\bitmap.bmp"
            Cursor.Current = Cursors.WaitCursor


                  sbar.Text = "Saving signature..."
            Dim stream As New System.IO.MemoryStream
            stream.Read(_signature.SignatureBits, 0, _signature.SignatureBits.Length)

            Try
                bmp.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp)
                bmp.Save(path, System.Drawing.Imaging.ImageFormat.Bmp)
            Catch ex As Exception
                Dim s_message As String = ex.Message
            Finally

            End Try
add the following to signature class:


Public Function ScaleImage(ByVal width As Integer, ByVal height As Integer) As Bitmap
        Dim result As New Bitmap(width, height)
        Using g As Graphics = Graphics.FromImage(result)
            Dim dstRect As New Rectangle(0, 0, width, height)
            Dim srcRect As New Rectangle(0, 0, _bmp.Width, _bmp.Height)
            g.DrawImage(_bmp, dstRect, srcRect, GraphicsUnit.Pixel)
        End Using
        Return result
End Function

and it will be OK :)
What is  _bmp?
here's the original sample I think: http://forums.devbuzz.com/m_41070/mpage_1/key_/tm.htm#41070

but basically, _bmp is


Private _bmp As Bitmap
So drawing one empty image onto another empty image?
Avatar of CISS

ASKER

alexy you da man!! That did the trick. we're almost home there are actually 2 images streamed in the code. The inbound side before storing in the database has a splash screen that says "please sign here" thats where we placed the above code. I actually need the image that comes back from. Sorry I placed the code in the wrong order of events.

Private Sub redrawSig(ByVal thisSigData As SignatureData)

            Dim _graphics As Graphics

            _graphics = Graphics.FromImage(_signature.Bmp)

            DrawSignature(_graphics, thisSigData)

            _signature.Invalidate()
ASKER CERTIFIED SOLUTION
Avatar of alexey_gusev
alexey_gusev
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of CISS

ASKER

Thank you so much it is greatly appreciated