vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
Go Back  Xtreme Visual Basic Talk > > > vb.net 2005 | Transfer image through Serial Port


Reply
 
Thread Tools Display Modes
  #1  
Old 02-09-2011, 07:48 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default vb.net 2005 | Transfer image through Serial Port


Hello.
I have a barcode scanner that beside scanning the barcode it also snaps an image.
I wrote a simple application that searching all ports locating in which one the scanner is connected and opening the port.

I can easily read any barcode and the send command to the scanner to pass me the image taken on the port, but i have a problem re-constructing the image from the bytes i read.

Code:
sendCommand() 
Dim img(SP.BytesToRead) As Byte 
SP.Read(img, 0, img.Length)
at this point i have a byte array (let's say with 11249 bytes in it)
Code:
img	{Length=11249}	Byte()
(0)	22	Byte
(1)	254	Byte
(2)	225	Byte
(3)	43	Byte
(4)	0	Byte
etc
.
.
Is it possible to save this array in a valid image format in VB.net?

Tried passing the array on a memorystream and creating a bmp from it but i'm getting an error "Parameter is not valid." when assigning the bmp(ms) because it needs a physical path from what i understand.

Code:
Dim ms As New System.IO.MemoryStream(img, 0, img.Length)
Dim bmp = New Bitmap(ms)
I can get the image from the scanner in any format needed (jpg,bmp etc) so no need to provide a precise solution just a general idea.

Thanks.
Reply With Quote
  #2  
Old 02-10-2011, 06:03 AM
Orca44 Orca44 is offline
Centurion
 
Join Date: Nov 2004
Location: Cape Town, South Africa
Posts: 124
Default

Have you tried the Bitmap.FromStream() method?
Reply With Quote
  #3  
Old 02-10-2011, 06:37 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

Code:
 
sendCommand()
Dim img(SP.BytesToRead) As Byte
SP.Read(img, 0, img.Length)

Dim ms As New System.IO.MemoryStream()
ms.Write(img, 0, img.Length)
ms.Seek(0, SeekOrigin.Begin)
Dim bmp As Bitmap = Bitmap.FromStream(ms)
Yes getting the same error "Parameter not valid"
Is there a chance of invalid image data causing this error?
I mean i'm getting the bytes and storing them in a byte array but i can't check if it''s an actual bitmap or not.
Reply With Quote
  #4  
Old 02-10-2011, 07:26 AM
Orca44 Orca44 is offline
Centurion
 
Join Date: Nov 2004
Location: Cape Town, South Africa
Posts: 124
Default

Wikipedia gives an explanation of what the header of the bitmap should look like.

A JPEG's header according to another source should consist of two bytes, 0xFF and 0xD8, followed by two bytes for both the width and height of the image in pixels.

Is your example an accurate representation of the byte-array you receive?

You might also try the Image.FromStream(), I am not sure if it will make much difference, but it might be a bit more generic that the Bitmap class.
Reply With Quote
  #5  
Old 02-10-2011, 07:29 AM
PlausiblyDamp's Avatar
PlausiblyDampvb.net 2005 | Transfer image through Serial Port PlausiblyDamp is offline
Ultimate Contributor

Forum Leader
* Expert *
 
Join Date: Nov 2003
Location: Newport, Wales
Posts: 2,058
Default

Which line is throwing the error?
__________________
Intellectuals solve problems; geniuses prevent them.
-- Albert Einstein

Posting Guidelines Forum Rules Use the code tags
Reply With Quote
  #6  
Old 02-10-2011, 07:46 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

Quote:
Originally Posted by Orca44 View Post
Wikipedia gives an explanation of what the header of the bitmap should look like.

A JPEG's header according to another source should consist of two bytes, 0xFF and 0xD8, followed by two bytes for both the width and height of the image in pixels.

Is your example an accurate representation of the byte-array you receive?

You might also try the Image.FromStream(), I am not sure if it will make much difference, but it might be a bit more generic that the Bitmap class.
I'm looking into that i think you re right probably populating the array with extra bytes.

Quote:
Originally Posted by PlausiblyDamp View Post
Which line is throwing the error?
Code:
 
sendCommand()
Dim img(SP.BytesToRead) As Byte
SP.Read(img, 0, img.Length)

Dim ms As New System.IO.MemoryStream()
ms.Write(img, 0, img.Length)
ms.Seek(0, SeekOrigin.Begin)
Dim bmp As Bitmap = Bitmap.FromStream(ms) //Parameter not valid
This one
Reply With Quote
  #7  
Old 02-10-2011, 07:52 AM
PlausiblyDamp's Avatar
PlausiblyDampvb.net 2005 | Transfer image through Serial Port PlausiblyDamp is offline
Ultimate Contributor

Forum Leader
* Expert *
 
Join Date: Nov 2003
Location: Newport, Wales
Posts: 2,058
Default

Does the barcode scanner come with any documentation as to what format the image is in? Failing that can you search on the internet for that particular model and see if this is documented anywhere.
__________________
Intellectuals solve problems; geniuses prevent them.
-- Albert Einstein

Posting Guidelines Forum Rules Use the code tags
Reply With Quote
  #8  
Old 02-10-2011, 08:22 AM
AtmaWeapon's Avatar
AtmaWeaponvb.net 2005 | Transfer image through Serial Port AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

There's a subtle mistake in your code. I'm not sure if it's the reason you get an error, but sometimes I find the .NET imaging classes to be finicky.

This code snippet demonstrates the error:
Code:
Dim items(3) As Integer
For i As Integer = 0 To items.Length - 1
    Console.WriteLine(i)
Next
How many items do you think that code will print? If you think it's 3, you're wrong. When you give an array bounds in VB .NET, the number you specify will be the upper bound, not the size, of the array. Since indexing starts at 0, there will always be upperBound + 1 items in the array. So the array in this example has elements 0, 1, 2, and 3 for 4 total elements.

Now let's look at your code:
Code:
sendCommand()
Dim img(SP.BytesToRead) As Byte
SP.Read(img, 0, img.Length)

Dim ms As New System.IO.MemoryStream()
ms.Write(img, 0, img.Length)
ms.Seek(0, SeekOrigin.Begin)
Dim bmp As Bitmap = Bitmap.FromStream(ms) //Parameter not valid
You make a Byte array with its upper bound as the number of bytes remaining in whatever SP is. Then you read as many bytes as will fit in the array. Here's the subtle error: your array has 1 extra element, so you're reading 1 byte past the end of the image. Is this enough to break Bitmap.FromStream? Possibly.

I have other concerns. I'm going to assume that SP is an instance of the SerialPort class since nothing else has a BytesToRead member.
  • How do you know that when sendCommand() completes the entire image has been transferred? If you read bytes while the image is still being transferred you'll only get the bytes that are present.
  • Maybe you aren't reading the number of bytes you think you're reading (perhaps because of the first point.) Read() returns the number of bytes that were read; you should probably check that return value:
    Code:
    Dim bytesRead As Integer = SP.Read(...)
    If bytesRead <> img.Length Then
        MessageBox.Show("Didn't read the expected number of bytes.")
    End If
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #9  
Old 02-11-2011, 02:20 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

I made it, i was reading extra bytes so the image was invalid, now i'm reading only the bytes of the image and i can save it successfully but i have the problem Atma said, i don't know when the whole image was transmitted,

Quote:
Originally Posted by AtmaWeapon View Post
[*]How do you know that when sendCommand() completes the entire image has been transferred? If you read bytes while the image is still being transferred you'll only get the bytes that are present.

Code:
Dim bytesRead As Integer = SP.Read(...)
If bytesRead <> img.Length Then
    MessageBox.Show("Didn't read the expected number of bytes.")
End If
I need a way to make this work cause sometimes i start populating the array with 0 or 1 byte read, i used sleep is any way better than this to be sure that the whole image is transmitted?

I don't know/have img.length before i complete reading all the bytes on the port so it can't be done with the above snippet.


Quote:
Originally Posted by PlausiblyDamp View Post
Does the barcode scanner come with any documentation as to what format the image is in? Failing that can you search on the internet for that particular model and see if this is documented anywhere.
I have the documentation but didn't help.
I can snap the image in whatever format i want, i will probably go with bitmap due to image clarity or jpeg for the smaller size didn't decide yet.

Last edited by georgepaska; 02-11-2011 at 02:37 AM.
Reply With Quote
  #10  
Old 02-11-2011, 09:32 AM
AtmaWeapon's Avatar
AtmaWeaponvb.net 2005 | Transfer image through Serial Port AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

Unfortunately there's no way for the serial port to know when it's "done" reading; that's a protocol-level problem. If you can't control the communication stream to tack on an image size, you're going to have to rely on a polling approach. If the serial port receives data that is not related to the image data, your only hope may be to read the header information to ascertain how large the file should be and/or decode it on the fly.

You can design something that's more or less asynchronous with the polling approach based on the BackgroundWorker class. The core polling approach would look like this:
Code:
* Decide on some timeout period. If you receive no data during this
    period, you can assume you are done with the file.

* Start timing the read operation
* While the timeout period has not elapsed
    * Read some data
    * If data was read, reset the timer.
    * Else:
        * If the timeout period has elapsed, exit the loop.
        * Sleep for some short period of time.
I'm not sure what a reasonable timeout period would be. For the purposes of this example, I'm going to use 5 seconds. Here's some code that you'll have to modify to get working since I have no idea how to set up the SerialPort:
Code:
Imports System.IO.Ports
Imports System.ComponentModel

Public Class SerialPoller
    Inherits BackgroundWorker

    Private _port As SerialPort

    Public Sub New(ByVal port As SerialPort)
        _port = port
    End Sub

    Public Sub StartPolling()
        Me.RunWorkerAsync()
    End Sub

    ' This runs on a worker thread. Don't try working with controls from here. Ask for more
    ' details if you want to update a progress bar (or read the documentation.)
    Protected Overrides Sub OnDoWork(ByVal e As DoWorkEventArgs)
        MyBase.OnDoWork(e)

        Dim data As New List(Of Byte)()
        Dim buffer(1023) As Byte
        Dim timeout As TimeSpan = TimeSpan.FromSeconds(5.0)
        Dim stopwatch As Stopwatch = stopwatch.StartNew()

        ' Loop until the timeout has elapsed; internal logic forces the exit.
        While True
            Dim bytesRead As Integer = _port.Read(buffer, 0, buffer.Length)
            If bytesRead > 0 Then
                ' If some bytes were read, copy them to the list and restart the timeout
                For i As Integer = 0 To bytesRead
                    data.Add(buffer(i))
                Next
                stopwatch.Restart()
            Else
                ' No data was read, check for timeout then sleep
                If stopwatch.Elapsed < timeout Then
                    Exit While
                End If

                System.Threading.Thread.Sleep(100)
            End If
        End While

        e.Result = data.ToArray()
    End Sub

End Class
It's pretty easy to use. Create an instance, add an event handler for the RunWorkerCompleted event, then call StartPolling(). This kicks off some code that calls OnDoWork() on a worker thread. Once that's finished, the RunWorkerCompleted event is raised. Here's a pseudo-example of using it:
Code:
Imports System.IO.Ports
Imports System.ComponentModel
Imports System.IO
Imports System.Drawing


Module Module1

    Private _sp As SerialPort

    Sub Main()
        _sp = New SerialPort()
        ' other configuration of the port

        ' Pretend the application doesn't quit here as if it were a WinForms app.
    End Sub

    ' Pretend this is an event handler for some button
    Sub GetImageButton_OnClick()
        SendGetImageCommand()
        Dim poller As New SerialPoller(_sp)
        AddHandler poller.RunWorkerCompleted, AddressOf Poller_FinishedPolling
        poller.StartPolling()
    End Sub

    ' This is called when the worker is finished running. It happens on the UI thread so it's OK to work with controls.
    Sub Poller_FinishedPolling(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
        Dim data() As Byte = CType(e.Result, Byte())
        Dim ms As New MemoryStream(data)
        ms.Seek(0, SeekOrigin.Begin)
        Dim img As Image = Image.FromStream(ms)
        '...
    End Sub

End Module
Again, this approach will only work if you can safely assume that the only data coming from the serial port will be image data and some long timeout with no data means it's done sending. If it can decide to take a break for a while or other data can be sent after the image is finished, this won't work very well.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #11  
Old 02-14-2011, 03:26 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

Quote:
Originally Posted by AtmaWeapon View Post
... If the serial port receives data that is not related to the image data, your only hope may be to read the header information to ascertain how large the file should be and/or decode it on the fly.
...
Again, this approach will only work if you can safely assume that the only data coming from the serial port will be image data and some long timeout with no data means it's done sending. If it can decide to take a break for a while or other data can be sent after the image is finished, this won't work very well.
Thanks Atma i was looking on a solution like this one at the end there is no way to completely avoid sleep so i'll go with it.

Although the first part is done the hard part is starting now.
I have the application ready and working but need to make it an acitvex that will be implemented at the site.

I have done a lot of reading but it seems that active x with .net is kinda hectic, should i bother trying to make it or you think it's better to re-write it in vb6 and then make it activex?
Reply With Quote
  #12  
Old 02-14-2011, 07:57 AM
AtmaWeapon's Avatar
AtmaWeaponvb.net 2005 | Transfer image through Serial Port AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

I think the problem's not going to be making .NET work with an ActiveX control, it's going to be making ActiveX work with modern web browsers (where "modern" means "something from the last decade".) If you want to write an application that's run client-side these days, Microsoft recommends Silverlight. Whether that's what you want to do or not, I think it's probably easiest to write an ActiveX control in VB6. I have no experience with making an attempt in .NET.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #13  
Old 02-15-2011, 01:08 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

Yeash sadly i'm using 2005 so Silverlight it's not an option.
Since the website project is made in ASP.net i would be able to use an ActiveX made with VB6?
Tried .NET made a dll and checked the "Register for COM Interop" but it seems that there is a problem using it.

I think i may came on a dead end here.
Reply With Quote
  #14  
Old 02-16-2011, 07:04 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

Server side the only thing i should do it's declare the activex as object in the aspx code with <object> tag including the class id?
Reply With Quote
  #15  
Old 02-16-2011, 07:43 AM
AtmaWeapon's Avatar
AtmaWeaponvb.net 2005 | Transfer image through Serial Port AtmaWeapon is offline
Fabulous Florist

Forum Leader
* Guru *
 
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,500
Default

I have no idea. ActiveX is an ancient technology and I have no experience with it, nor is it likely many other .NET developers can help. For ActiveX, you should probably post questions in the VB6 sections of the forums.
__________________
.NET Resources
My FAQ threads | Tutor's Corner | Code Library
I would bet money 2/3 of .NET questions are already answered in one of these three places.
Reply With Quote
  #16  
Old 02-16-2011, 08:13 AM
georgepaska georgepaska is offline
Newcomer
 
Join Date: Nov 2007
Posts: 8
Default

I see let me re-phrase it then.
The web application we have runs in like 10 terminals.
All of them can save new barcode data by scanning a box and inserting a new entry.

What i want to do is to allow 2 of these terminals when insert a new entry to also create a text file with the barcode as filename in a selected path in client's machine.

How this can be done if not with activex?

Thanks.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
 
vb.net 2005 | Transfer image through Serial Port
vb.net 2005 | Transfer image through Serial Port
 
-->