Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Converting a bitmap generated by a webcam to a jpg 1

Status
Not open for further replies.

tedsmith

Programmer
Nov 23, 2000
1,762
0
0
AU
I am trying to find ways to improve converting a bitmap generated by a webcam to a jpg so it can be sent faster via a network to another computer.

My problem is -

I tried GDIplus as per an old strongm examples with, instead of saving the jpg to file, I used:-
GdipCreateFromHDC Picture2.hDC, myGraphics
GdipDrawImage myGraphics, gdiImageTarget, 0, 0

This does quickly paint a jpg picture over a picturebox but this is wiped out by any object moving over it and it's .picture = 0 so there is nothing to send! It seems to be drawing only to the screen, not the picturebox.

Is there a way of using GDIplus to produce a data stream or fill a picturebox.picture like a loadpicture statement does so it can be sent over a network?

Currently I use AviCap32 feeding the webcam to the clipboard.
I then send the BMP in the clipboard over the network in a propertybag without any problem.

Using GDIplus I am able to capture the picture and convert it to the jpg picture'painted'box but I cant send this picture to the network.

GDIplus often freezes the app when you close it needing removal by task manager processes.

I haven't been able to get WIA to work on Win7 so I cant use this either unless someone has an answer to this separate problem!
 
I thought this was all about video capture and "streaming" the frames over TCP to be displayed there. If so, what use would it be to send any "text" back to the capture program sending the video?


I think I have my "capture and send a stream of JPEGs" code working pretty solid now. I was able to completely eliminate the use of Preview windows for capture/streaming, which means the program will send video even when minimized. I haven't dug into it yet but this might even work as a Windows Service.

No PropertyBags used at all here. WIA 2.0 is being used to convert captured raw bitmaps to JPEG image file data for sending and to convert this data back into StdPicture objects for display. That logic is pretty well isolated so you could easily rip out WIA and use other techniques for handling the JPEG processing.
 
Yes
Thanks for all your help.
I am grateful to you all for finally explaining the subject in terms I can understand.

I am not asking for the code this time - just a comment on my proposed method as the change to GDI+ stream impinges on my app.
I previously used propertybags and a stream to accumulate the BMP pic because they gave an extra check on the integrity of the network data and were very convenient to program and quick in operation.

As I obviously should use strongm's GDI+ method or WIA, I will dispense with propertybags entirely and the reasons I included this last question was the change impinges on transmission of other things and if anyone else had found a more elegant method of mixing text and pics coexisting. I obviously don't want to put the GDI+stream into a property bag too to differentiate it!

The reason I have to send text back is that the client is an odd sort of information display at bus stops that gather information around it such as a sensor to tell when a bus pulls up (and relays this back to a control room). I also must send a verification that the information being displayed has been received from the server is exactly what was sent.

My setup using AVICap and strongm's GDI+ stream doesn't NEED any picture or image boxes or any forms visible to send pics. It just happens to display the camera locally as well on 3 multiple monitors and text or graphic information.

Incidently, I found I can have 16 clients feeding to the one server Windock_Dataarrival and all showing their pictures in shrunk indexed image boxes(15) that are magnified when you click on them. I initially load indexed winsocks(15) each with a different local port, dimmed MyStream(15) and SentStreamSize(15) so they don't get confused when 2 cameras send nearly at once. It works without a hitch even with 1meg BMPs - now will be even quicker with 20k JPGs.
 
I'm not sure why you need to send an "ok" back at all. The source sending JPEGs (not sure which you call client and which server) can tell when it can send another via SendComplete events. By making this a half-duplex protocol you slow things down quite a bit, including Nagle issues that make it even worse.

But let's say you just insist.

Your "back channel" with Acks and Msgs can be managed entirely differently. But it will still need message framing.

This could be via length prefix or terminating char(s)/byte(s):

Code:
.SendData "1|"

.SendData "2:message text|"

Note that the "message type" could be text-based too (above). I'm not sure sending a Long buys you anything but extra grief to handle it on receive. Sending "ok text" after a message type 1 seems redundant. If your message type codes are all 1 character (even 0-9, A-Z gives you 36 types) then you can even dispense with the colon.
 
Thanks
Client is the one with the camera, Server is the one that receives it.
There are 16 clients(cameras) and one server.

The OK has nothing to do with sending the JPG from Client to Server. It is an acknowledgement that data has been sent in the other direction from Server to CLient.
Its just that the OK is sent in the same direction as the JPG but in response to a text data transmission from the server to the client at an unrelated time interval.

I an concerned that the OK might coincidentally be sent at the same time as the picture so I need to accurately separate them. This is where Propertybag was so useful. They have to use the same port.

With the propertybag I used a Sendcomplete signal but found this unrelaible depending on the speed of the computers. This sendcomplete uased to get attached to the end of the intital packet and was lost so I had to put in a 30ms delay before the sendcomplete fired.
With strongm'm method this delay is not needed so the speed is always at maximum.

I notice if you play around with the LAN plug while transmitting to simulate a dodgy network you can get Strong's method to eventually fail due to overflow on SetStreamSize. So I put in an error trap to make this 0.

The client has a dual purpose:
1. sending pictures of the bus arrival when a motion sense routine detects a bus arriving or leaving. This does not need acknowledgement.
2. locally showing departure and message information on it's screens. This does need acknowledgement because there is no one in authority to check it was received. It might show the previous bus leaving resulting passengers getting on the wrong bus.
 
The reason for "OK" is that if the message received by the client does not conform to guidelines or is not a valid picture, it will echo back "Fault" followed by description of the error instead of "OK"
If no message is echoed back at all, the server will show a Fault one second after transmitting.
I still use propertybags for the transmission Server to Client as this is much smaller and the code is already there. (I'm lazy)
 
>I previously used propertybags and a stream to accumulate the BMP pic because they gave an extra check on the integrity of the network data and were very convenient to program and quick in operation.

If you find property bags so useful for merging data and handshaking information, with ease of programming, you can still use it with your client to server communication. After encoding your picture with GDI+ to a jpeg stream using GdipSaveImageToStream function, use strongm's LoadPictureFromStream or LoadPictureFromStream2 function above to convert that jpeg stream into a vb picture again.

As I told above, these OLE functions preserve the originality of the picture. So if you put the resulting StdPicture into a property bag, it will not inflate the bag and maintain its original size matching with the size of the jpeg stream. You can put additional handshaking information in the same bag and send it over the network to the server. There you can extract the StdPicture directly and can display it without doing any conversion at all!

>Client is the one with the camera, Server is the one that receives it.
If this is the correct definition, then swap all servers and clients in my previous post to understand it correctly.

I would like a small modification to strongm's LoadPictureFromStream/LoadPictureFromStream2 functions. The argument should be declared as olelib.IStream instead of just IStream. This is because ISteam interface is defined in both OLE and GDI+ library, but the one in GDI+ does not expose the Seek method.

So, if you have referenced both GDI+ and OLE library in your project, plain IStream definition will not work if you have GDI+ listed above OLE in References.
 


>PictureFromRawBits also retains the "originality" of the Picture object, in contrast to CreatePictureFromGDIPlusImage function. So if you put the resulting picture into a PropertyBag and measure its size using Ubound(Contents), it will return the same size as the original jpeg in compressed format

I don't believe this is correct. Which means that

>these OLE functions preserve the originality of the picture. So if you put the resulting StdPicture into a property bag, it will not inflate the bag and maintain its original size matching with the size of the jpeg stream

is also incorrect.

I'll repeat, the Picture object holds a BITMAP (plus some additional bits and pieces). The Handle property (described in the documentation as an OLE_HANDLE (int)) is in fact an hBitmap.
 
(Ok, to be pedantic a Picture object can also hold a metafile, but let's not complicate things)
 
>I'll repeat, the Picture object holds a BITMAP ... The Handle property ... is in fact an hBitmap.

I never contradicted that. After all, we pass Picture.Handle to Win32 GDI functions expecting an hBitmap all the time.

But both of my statements above were based on my observations.

I just tested again. I placed a 800x600 jpg in a picture box, whose file size is 56.4 KB. I used your jpg compression code in your first post above to compress the picture. After calling GdipSaveImageToStream, I used your LoadPictureFromStream2 function to convert mystream back to an StdPicture object.

Putting that picture in a property box and querying its size returned 22296 bytes (well, decrease in size from 56 KB is explained due to substantial loss of quality (25%)). If the Picture object were saved in the property bag as a BITMAP, it would have occupied 800 x 600 x 3 = 1440000 + overhead bytes instead.

See this again in the example below. This time I use PictureFromRawBits function.
___
[tt]
Private Declare Function CLSIDFromString Lib "ole32" (ByVal lpsz As Any, pclsid As Any) As Long
Private Declare Function CreateStreamOnHGlobal Lib "ole32" (ByVal hGlobal As Long, ByVal fDeleteOnRelease As Long, ppstm As Any) As Long
Private Declare Function OleLoadPicture Lib "olepro32" (pStream As Any, ByVal lSize As Long, ByVal fRunmode As Long, riid As Any, ppvObj As Any) As Long
Private Declare Function GlobalAlloc Lib "kernel32" (ByVal uFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalLock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" (ByVal hMem As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSource As Any, ByVal dwLength As Long)
Const GMEM_MOVEABLE = &H2

Function PictureFromRawBits(bytes() As Byte) As IPicture
Dim cbMem As Long, hMem As Long, IPic(15) As Byte, istm As Object
'data length
cbMem = (UBound(bytes)) - LBound(bytes) + 1
'allocate global memory block
hMem = GlobalAlloc(GMEM_MOVEABLE, cbMem)
'copy picture data to global memory block
CopyMemory ByVal GlobalLock(hMem), bytes(LBound(bytes)), cbMem
'reset lock count
GlobalUnlock hMem
'create stream object from global memory
CreateStreamOnHGlobal hMem, 1, istm
'fill the Guid of IPicture interface from its CLSID
CLSIDFromString StrPtr("{7BF80980-BF32-101A-8BBB-00AA00300CAB}"), IPic(0)
'create picture from stream object
OleLoadPicture ByVal ObjPtr(istm), 0, 0, IPic(0), PictureFromRawBits
'free global memory
GlobalFree hMem
End Function

Private Sub Form_Load()
Dim B() As Byte, File As String
File = "C:\Users\Public\Pictures\Poster.jpg"
Open File For Binary As #1
ReDim B(LOF(1) - 1)
Get #1, , B
Close

Dim pic As StdPicture, pb As PropertyBag
Set pic = PictureFromRawBits(B)
Set pb = New PropertyBag
pb.WriteProperty "Picture", pic

Debug.Print "File name:", File
Debug.Print "Picture width:", Round(ScaleX(pic.Width, vbHimetric, vbPixels))
Debug.Print "Picture height:", Round(ScaleX(pic.Height, vbHimetric, vbPixels))
Debug.Print "File size:", UBound(B) + 1 'FileLen(File)
Debug.Print "Size of property bag:", UBound(pb.Contents) + 1

Unload Me
End Sub[/tt]
___

The picture I used in the code is same as I referenced above. Here is the debug output.
[tt]
File name: C:\Users\Public\Pictures\Poster.jpg
File size: 57842
Picture width: 800
Picture height: 600
Size of property bag: 57900
[/tt]
Once again the property bag has the same size as the jpg file. Slight difference is due to the property bag overhead. A true color bitmap of same dimensions would have occupied more than 1.37 MB.

>plus some additional bits and pieces
Well, my theory is that, somewhere in those bits and pieces, the original stream which was used to create the picture is also preserved, and same is written to the property bag instead of the whole BITMAP data. Same stream is written to .frx files when we load a jpg picture in the picture property of a form, for instance. Otherwise, loading a jpg or a bmp file would have made no difference on the size of .frx file, and same would have reflected in the size of resulting exe file.

Well, there is another interesting observation. While PictureFromRawBits (and thus OleLoadPicture) appears to preserve the original stream, LoadPicture does not.
So if we create a Picture using LoadPicture, the resulting picture always occupies the size as that would be required by the BITMAP. See below.
___
[tt]
Private Sub Form_Load()
Dim File As String
File = "C:\Users\Public\Pictures\Poster.jpg"

Dim pic As StdPicture, pb As PropertyBag
Set pic = LoadPicture(File)
Set pb = New PropertyBag
pb.WriteProperty "Picture", pic

Debug.Print "File name:", File
Debug.Print "File size:", FileLen(File)
Debug.Print "Picture width:", Round(ScaleX(pic.Width, vbHimetric, vbPixels))
Debug.Print "Picture height:", Round(ScaleX(pic.Height, vbHimetric, vbPixels))
Debug.Print "Size of property bag:", UBound(pb.Contents) + 1

Unload Me
End Sub[/tt]
___

This time the output was as below. We see that the size of the property bag has inflated to the size of the property bag.
[tt]
File name: C:\Users\Public\Pictures\Poster.jpg
File size: 57842
Picture width: 800
Picture height: 600
Size of property bag: 1440112 [/tt]
 
Oops! Feeling very drowsy at the moment.

>We see that the size of the property bag has inflated to the size of the property bag BITMAP.
 

This would seem to be an ... oddity ...

Particularly since if you dump pic.type it definitely thinks it is a bitmap (returning vbPicTypeBitmap)

Ah - and I think I see what is going on here. And it might be quite handy ... just need to investigate a little further. If you want to look, it's related to OleLoadPicture's fRunmode parameter (try changing it to 1, rather than 0, and you'll see it now works just like VB's LoadPicture). It indicates that StdPicture is somewhat more clever than previous investigations had suggested, in that we can keep a copy of the source data cached along with the bitmap it is turned into and - and this is the surprisong bit - it is this cache plus some state data (which is why the proopertybag is slighly bigger than the raw jpeg file itself) that gets serialised when whe try to persist it (which is what we are doing when we stick it into a propertybag)
 
Yes, I see the effect of fRunmode parameter. In fact, if we change the KeepOriginalFormat property of returned picture to false, using its IPicture interface, the effect is same. The modified code fragment shows this.
[tt]
Dim pic As IPicture, pb As New PropertyBag
Set pic = PictureFromRawBits(B)
pic.KeepOriginalFormat = False
pb.WriteProperty "Picture", pic
[/tt]
This causes the pic object to loose its cached data and save complete BITMAP in property bag.

However, doing the reverse is not possible, perhaps, because the cached data has already been thrown away. So doing the same thing with a picture returned from LoadPicture fails. You cannot set KeepOriginalFormat to True once it has been set to False.
[tt]
Dim pic As IPicture
Set pic = LoadPicture("C:\Users\Public\Pictures\Poster.jpg")
pic.KeepOriginalFormat = True '<- Fails[/tt]
 
I think the properytybag will always be slightly bigger than the data because it contains such things as the start and end characters and name of the "bag" but the pic or data after readproperty is the same.

I am more than happy with strongm's original solution and dont really want to go back to propertybags

The final problem was how to seperate pics and text reliably.
If you sent a pic immediately after data is received, the acknowledgement OK sometimes gets tacked onto the pic before or after it in the one DataArrival instance - which is hard to separate.
Maybe I should always send dummy data when no real text is required so the dataarrival always treats every reception the same?

The following code seems to work but sometimes misses a pic if you send a lot text and pics together in quick succession.
Any comments would be appreciated

Code:
'++++++++++++++++++++++++++++++++ WINSOCK SERVER ROUTINES connecting to all bus stop clients by Index ++++++++++++++++++++++++++
Private myStream(16) As olelib.IStream

Sub Winsock_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Dim StreamStats As olelib.STATSTG
Dim gdiImageTarget As Long
Dim GpInput As GdiplusStartupInput
Dim Token As Long
Dim myGraphics As Long
Dim buffer() As Byte
Dim Message As String
On Error GoTo WDAError
SelectMessageType:
Select Case SentStreamSize(Index)
Case 0
    'Start of a new transmission
    Winsock(Index).GetData SentStreamSize(Index), vbLong
    MainForm.EventList.SelText = "Got Stream size" & SentStreamSize(Index) & vbCr    
    If SentStreamSize(Index) = 1 Then
        'Acknowledgement of received departure data at bus stop
        SentStreamSize(Index) & vbCr
        MainForm.lblIndicator(Index).Caption = vbCr & "OK"
        Updated(Index) = 0
        'check if more data appended
        ReDim buffer(0) As Byte ' reset input buffer
        Winsock(Index).GetData buffer, vbArray Or vbByte ' read the  byte array
        Select Case UBound(buffer)
            Case 5 To 255
                'further report message (text encoded as binary) 
                For a = 0 To UBound(buffer)
                    Message = Message & buffer(a) 'form message
                Next
                MainForm.BusStopErrors.Caption = "Faulty " & MainForm.BusStop(Index).Caption & " " & Message 'fault reported from bus stop
                SentStreamSize(Index) = 0
            
            Case Else
                'picture was appended to initial received data
                SentStreamSize(Index) = Val(buffer(5) & buffer(6) & buffer(7) & buffer(8))
                GoSub ProcessPicture
            
        End Select
    End If
    If SentStreamSize(Index) = 2 Then
        'received bus presence detect from bus stop
        'Future ?????? write routine to receive 1=bus arrived, 0=bus just departed & show model bus graphic at stop if no VID
   
    End If
    '
Case Else
    'large size pic without text so start accumulating camera picture data into the stream
    ReDim buffer(0) As Byte ' reset input buffer
    Winsock(Index).GetData buffer, vbArray Or vbByte ' read the byte array
    GoSub ProcessPicture
End Select
If Token Then GdiplusShutdown Token
endWDA:
On Error GoTo 0
Exit Sub
    
ProcessPicture:
myStream(Index).Seek 0, STREAM_SEEK_END
    myStream(Index).Write buffer(0), bytesTotal ' append to a stream
    myStream(Index).Stat StreamStats, STATFLAG_NONAME
    If SentStreamSize(Index) <= StreamStats.cbSize * 10000 Then 'we've accumulated all the data
        GpInput.GdiplusVersion = 1
        If GdiplusStartup(Token, GpInput) <> Ok Then
            MainForm.ShowErrors "Error loading GDI+! [WinsockServer]"
        Else
            GdipLoadImageFromStream myStream(Index), gdiImageTarget 'load GDI+ image from stream (which in this case contains a JPEG)
            ' At this stage we have loaded a jpg into GDI+ from a stream
            ' so we can reset that stream for reuse
            ResetStream Index
            ' working with a StdPicture object created from the GDI+ image
            MainForm.EventList.SelText = "total Image received " & UBound(buffer) & vbCr
            Set MainForm.ImageCamera(Index).Picture = CreatePictureFromGDIPlusImage(gdiImageTarget)
            MainForm.ImageCamera(Index).Visible = True
            GdipDisposeImage gdiImageTarget
            GdipDeleteGraphics myGraphics
         End If
         SentStreamSize(Index) = 0
    End If
Return
WDAError:
MainForm.ShowErrors Error & " [WinsockServer]"
SentStreamSize(Index) = 0
Resume endWDA
End Sub
 
Whew, lots of problems there.

You cannot rely on the bytesTotal value passed to DataArrival, contrary to what the original docs suggest. This was covered in some MS KB article, somewhere around VB6 SP3. Instead use [tt]UBound(buffer) + 1[/tt], or risk a value that is too small and you'll truncate your data when you write it to the Stream.


Never, never .GetData into a Long. Only use Byte arrays. What if you haven't received 4 bytes yet? What if you've received more than 4 bytes already? Kaboom! This was also covered in an MS KB article sometime well after VB6 was released. It really only works in simple "dummy" projects where things don't happen very quickly.

Probably why you have that funky error handling in there, hmm?

Strictly speaking, it is illegal to send Long values over TCP/IP anyway as part of a protocol. Only big-endian values are considered acceptable. However I do it myself sometimes, even though it makes such protocols Windows-specific. Winsock libraries provide htonl() and ntohl() functions for handling this correctly. This is more a "nice to have" rather than a "must have" though.


As written this code will fail miserably unless you stick with a chatty, slow, half-duplex protocol. Doing things correctly means the logic works for both half- and full-duplex protocols.

Remember, on any given DataArrival you are only guaranteed one byte of data is available. There might be a little more, or much more, or even part of two or more messages. You really need to buffer everything you get on a DataArrival, and only then try to parse out and process any whole messages in the buffer.

Failing to do this means trouble. I'm starting to understand why you feel you need these "ok" acks. TCP is a reliable protocol by its nature, there should be no reason at all to "check that stuff gets there right" but your logic has gaping flaws.
 
Thanks for the time you people have spent examining my new proposal, I appreciate it very much.

I just can't wait to see strongm's response to this!
This use of bytestotal and vblong are straight out of his example.

The use of vbLong as a winsock receive format in the first getdata, I would have thought is just a handy way of telling getdata to receive only 4 bytes.
The first block of data to be received contains the Streamsize and the first 8k of the picture.
It does seem to actually get only the first 4 bytes, leaving the others behind to be detected by the next getdata statement. Getting only 3 bytes at the start of transmission with the rest to follow would be extremely unlikely and would signify a fault like somebody pulling out the LAN plug that would be soon known by my OK method.

When the text and pic are occasionally transmitted with no gap between them (eg a bus arrives at the same time an OK has to be sent), they get mixed up with the pic I receive all together in one dataarrival operation
Streamsize (text 1)
OK
Streamsize (Picture size >20k)
Picture
That is why I have to separate them with the Else stuff and the processpicture in a separate subroutine so it can also be used when only a pic is received. I suspect I have something wrong here.

I always need more than 1 byte to convey the streamsize and I need the streamsize to be sure to capture all of it. (previously I used a fixed end code)

Why is my error routine 'funky'? I though that is what error routines are for!
Because the client is unattended it has to never show an error message or stop working if any errors of any kind happen - it just let the control room know.

The NEED for acknowledgement of only the text has nothing to do with the current problem because the text data (to be acknowledged) is sent the opposite way to the pictures.

The OK alert is not sent back just to confirm the network.
The handy thing about the OK idea is that it alerts if anything at all is wrong with the whole system including whether it got to the right bus stop (except if the fluro tubes in the LCD monitors have blown - but I'm even working on that)
If an OK is not received within 1 second an alert shows on the control room monitor.

This project (that I have been tweaking every few years for the last 26 years when the customer wanted a change) seems strange to many because generally a person is at the receiving end of a system and can see immediately when there are problems. Mine is the opposite with unattended clients so I have had to adopt many other unconventional methods over the years to make it keep working 100%at all costs.

My very first server version was written in DOS basic, RS232 and client Commodore 64s feeding TV sets in 1986!

 
>strongm's original solution

I think I'd be using either my later

LoadPictureFromStream
or
LoadPictureFromStream2

functions at the receiving end since they both eliminate the requirement to implement any GDI+ code at the receiving end, thus simplifying things somewhat

>I just can't wait to see strongm's response to this!
>This use of bytestotal and vblong are straight out of his example.

As I've previously pointed out, my code examples in this forum are not intended to be production code quality. They are generally designed to illustrate a possible avenue of attack.
 
Thanks however
I wouldn't have thought that your later versions you mention would have any bearing on the current problem of reliably separating pictures and text?

The use of bytestotal and vblong seem to work perfectly as long as I only transmit a picture (contrary to the previous advice). I only get unreliability when I mix them so I ma working an another approach.

>not intended to be production code quality.
I understand this and modify to suit or add other things where necessary to make it bomb proof.
I have even guilty of not using some of your suggestions if I find an alternative that performs better to suit the circumstances.
I am sure you wouldn't be suggesting a principle that I shouldn't be using at all.
 
As the manual says for GetData:
data

Where retrieved data will be stored after the method returns successfully. If there is not enough data available for requested type, data will be set to Empty.

If you pass a Long there, you'll frequently not have enough data to fit yet (4 bytes). When it tries to return Empty your Long would likely end up being 0.

From what I can see in your code a 0 there makes you exit the event handler without doing anything, apparaently "by guess and by golly" rather than intent. When more data is received you go through this again until there are 4 bytes or more to get with GetData.

Even then you ignore the rest of the received data and fall out once more, waiting for more data to be received to cause another DataArrival event. When this occurs, you blindly GetData everything received so far and treat it as the image data or text... even if it contains part or all of the next (or next 12) messages!

When this code blows up on some logic error your "error handler" muddies the waters by setting [tt]StreamSize(n) = 0[/tt], which appears to tell the rest of your code there "ditch everything and assume the very next byte received is exactly the beginning of a new message" - which it just might, on rare occasion. But rather than an error handler you have an error maker there.


I won't attempt to contribute further because it just gets frustrating for all involved.
 
>I wouldn't have thought that your later versions you mention would have any bearing on the current problem of reliably separating pictures and text?

No
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top