Link to home
Start Free TrialLog in
Avatar of esps
esps

asked on

Convert binary to .jpg vb 2005

Hi Experts,
Attached is a binary file which I need to save to disk exactly as it is.
There may be header info missing. The input file come from a digital camera connected to a serial port.
I need to get it to a jpg that I can open as a jpg
 
 VB 2005 saves it as a uni-code string when you open a file using a stream. You then lose some data. After trying ising method of opening a stream (does not work) I tried this which also does not work:
 
DataString holds the complete correct binary data. I cut and pasted it into a hex editor and it is correct.
 
 
 BinaryStream = CreateObject("ADODB.Stream")
 
        'Specify stream type - we want to save binary data.
        BinaryStream.Type = adTypeBinary
 
        'Open the stream And write binary data To the object
        BinaryStream.Open()
        BinaryStream.Write(DataString)
        'Save binary data To disk
        BinaryStream.SaveToFile("Testfile.jpg", adSaveCreateOverWrite)

please help
jpgimage.jpg
Avatar of Joel Coehoorn
Joel Coehoorn
Flag of United States of America image

Whenever I see CreateObject() in VB.Net I cry a little inside.  

In the code you posted, you create a stream, but never connect that stream to a data source.  Where does the data for the stream come from? (I don't mean the camera- I mean how is your program attaching that stream to the camera).

There's no guarantee that a camera is sending a picture in jpeg format, or that it's sending picture data at all.  There's a lot of control information that has to be sent back and forth, and multiple pictures could come in a batch.  I'll trust that you're using the camera's API correctly to get a picture, but what if this camera uses RAW data?
Avatar of esps
esps

ASKER

The format would be RAW data indeed. The camera in question is not a conventional digital camera but a custom built unit. Unit consist of a miniture camera mounted on a PC board. The manufacturer has indicated that if I send 55Hex to the camera it will return a binary stream of a single picture taken. When  saved correctly this should be a jpg picture format.  
The key there is 'saved *correctly*'.  If the camera is sending RAW data there may be some non-trivial conversion that needs to happen.

Let's start real simple.  Try this and see what happens:
    Function GetImageFromSerialPort(ByVal PortName As String) 'COM1, COM2, etc'
        Dim p As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort(PortName)
        Dim b() As Byte = {85} '55Hex'
        p.Write(b, 0, 1)
        p.BaseStream.Flush() 'just one byte will probably be buffered'
        Return Image.FromStream(p.BaseStream)
    End Function

Open in new window

I want to tweak that code just a bit- forgot the return type on the function.  You may also need to set the baud rate, parity, and stopbits with the openserialport call.
    Function GetImageFromSerialPort(ByVal PortName As String) As System.Drawing.Image 'COM1, COM2, etc'
        Dim p As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort(PortName)
        Dim b() As Byte = {85} '55Hex'
        p.Write(b, 0, 1)
        p.BaseStream.Flush() 'just one byte will probably be buffered'
        Return Image.FromStream(p.BaseStream)
    End Function

Open in new window

Avatar of esps

ASKER

We are getting there!
Using the Serialport class, I now have the code as below:
        SerialPort1.Open()
        Dim databytes As Byte() = New Byte() {&H55, &H1}
        SerialPort1.Write(databytes, 0, databytes.Length)
        Dim Count As Integer = SerialPort1.BytesToRead
        Dim Buffer(0 To Count - 1) As Byte
        SerialPort1.Read(Buffer, 0, Count)
The card(camera) responds find and returns a chunk of data to the buffer.
How should I now proceed to try and save this as a jpg (assuming the format is ok)
See if this works:
    Sub SaveImageFromSerialPort(ByVal PortName As String, ByVal FileName As String)
        Dim p As System.IO.Ports.SerialPort = My.Computer.Ports.OpenSerialPort(PortName)
        Dim b() As Byte = {&H55, &H1} '55Hex'
        p.Write(b, 0, b.Length)
 
        Dim buf(4096) As Byte
        Using fs As New IO.FileStream(FileName, IO.FileMode.CreateNew, IO.FileAccess.Write), _
              output As New IO.BinaryWriter(fs)
 
            Dim count As Integer = p.Read(buf, 0, 4096)
            While count > 0
                output.Write(buf, 0, count)
                count = p.Read(buf, 0, 4096)
            End While
        End Using
    End Sub

Open in new window

Avatar of esps

ASKER

Hi jcoehoorn
I've adapted your sub as below: ( note the change to count where I subtract 1 from count for each iteration of the loop. As it was, the loop was endless. Please check if what I did is ok.
I am uploading the file that is written. It does not open as an image. Is it possible to check what is wrong with the file?
regards

Sub SaveImageFromSerialPort(ByVal PortName As String, ByVal FileName As String)
        If SerialPort1.IsOpen Then
            SerialPort1.Close()
        End If
        SerialPort1.Open()
        Dim databytes As Byte() = New Byte() {&H55, &H1}
        SerialPort1.Write(databytes, 0, databytes.Length)
        Dim buf(4096) As Byte
        Using fs As New IO.FileStream(FileName, IO.FileMode.CreateNew, IO.FileAccess.Write), _
              output As New IO.BinaryWriter(fs)

            Dim count As Integer = SerialPort1.Read(buf, 0, 4096)
            While count > 0
                output.Write(buf, 0, count)
                count = count - 1
                'count = SerialPort1.Read(buf, 0, 4096)
            End While
        End Using
    End Sub
test.jpg
You commented out the line where you read from the port in the loop, so you're never updating buf and end up writing the same bytes over and over again.

The Read() method should return the number of bytes read from the stream.  I'm not sure why it wasn't working before.

Let's try this again.  This time my method allows you to pass your serialport1 as a parameter instead of the port name, and I added a redundant check to the loop to see if we still have bytes to read:
    Sub SaveImageFromSerialPort(ByRef Port As IO.Ports.SerialPort, ByVal FileName As String, Optional ByVal BufferSize As Integer = 4096)
        'get port ready to send
        If Port.IsOpen Then Port.Close()
        Port.Open()
 
        'send request for next image
        Dim databytes() As Byte = {&H55, &H1} '55Hex'
        Port.Write(databytes, 0, databytes.Length)
 
        'get ready to read data
        Dim buf(BufferSize) As Byte
        Using fs As New IO.FileStream(FileName, IO.FileMode.CreateNew, IO.FileAccess.Write), _
              output As New IO.BinaryWriter(fs)
 
            'read from camera and write to destination file
            Dim count As Integer = Port.Read(buf, 0, BufferSize)
            While count > 0 AndAlso Port.BytesToRead > 0
                output.Write(buf, 0, count)
                count = Port.Read(buf, 0, BufferSize)
            End While
 
            'clean up and finish
        End Using
    End Sub

Open in new window

Avatar of esps

ASKER

While count > 0 AndAlso Port.BytesToRead > 0
after the read from camera, count has a value of 2588 and BytesToRead is 0
the write therefore does not take place and an empty jpg is written
ASKER CERTIFIED SOLUTION
Avatar of Joel Coehoorn
Joel Coehoorn
Flag of United States of America 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 esps

ASKER

Result is as follows:
First iteration on while, port.bytestoread = 2556, count = 2556, buf = 4097, bufersize = 4096
Second iteration port.bytestoread has become 0 and loop ends.
jpg created is 3KB in size which won't open.
I figured that was too small.  Forget the loop for now.  Just try to read twice and see what happens on the 2nd read.  Does it give you an exception?  no data?  The same data?  different data?
Avatar of esps

ASKER

The second time I get to count = port.read it hangs.
Way up in your first post you said you were able to past the correct data into a hex editor.  Are you able to save that manually pasted data to disk and open it correctly?  How does it compare with what we just retrieved?
Avatar of esps

ASKER

What I meant was that when opened with a hex editor, there is a lot of data that I assumed is correct.
If what we are doing is correct then something with the camera must be the problem
It may be time to talk to the manufacturer about exactly what they mean by 'saved correctly'.
Avatar of esps

ASKER

I'll do exactly that. Thank you very much for all your effort to date. We are way past awarding points. I owe you big time. Should I close this threadand award the points anyway? Hope I can return the favour somehow. How will I let you know when I have an update from the manuafacturer?
best regards
esps@iafrica.com
That sounds fine.  When you hear back from the manufacturer you'll want to open a new question anyway- old questions don't typically get much new attention once they're more than a day old or have more than a couple responses.
Avatar of esps

ASKER

Thanks again