TCPSocket stream to picture

  1. 2 months ago

    Hello,
    on server TCPSocket i have a picture loaded as binary stream.
    is it possible to send this binary stream via a TCPSocket "write" method to a socket-receiver and convert it back to picture without saving it to a file first and put it e.g. into a canvas?

  2. shao s

    is not verified Sep 13 Sudbury, Ontario, Canada

    http://docs.xojo.com/index.php/Picture.FromData

  3. Edited 2 months ago

    Thanks!

    Is there a save way to check if the image was transferred completely? Is "send complete" fired when finished sending and has the "receiver socket" then received it completely?

  4. Joost R

    Sep 14 Pre-Release Testers, Xojo Pro The Netherlands

    Collect some info about the picture before sending it, send that info bundled with the picture-data and check in the receive event of the receiving socket.

  5. i' searched the forum and did this:

    on Server side sending picture

    dim f as FolderItem=GetOpenFolderItem("")
    dim bs as BinaryStream
    if f <> nil then
    	bs=bs.Open(f,false)
    end if
    dim ret() as TCPSocket=MainServerSocket.ActiveConnections
      for i as integer= 0 to UBound(ret)
    	while not bs.eof
    		ret(i).write(bs.read(512000)+chr(13)+chr(10))
    	Wend
    next

    and on receiver side in dataavailable:

    dim Buffer as String
    Dim boundary As Integer = Instr(Me.LookAhead, chr(13)+chr(10)) 
    		
     Do Until boundary = 0
    		Buffer = Buffer + Me.Read(boundary)
    		boundary = Instr(Me.LookAhead, chr(13)+chr(10)) 
    Loop
    		
    dim p as Picture	
    p=Picture.FromData(Buffer)
    Canvas1.Backdrop=p
    Canvas1.Invalidate

    i can send a image which is received and displayed in the canvas, but if i send a second image the canvas is empty.
    Also when sending a large image, the canvas flashes short (with the image) and then is empty.

    Any suggestions?

  6. Edited 2 months ago

    ok, shure i have to empty the internal buffer afterwards..
    sock.purge

    but the problem with large images is still there, it loads, flashes shortly and then the canvas is empty.

    edit: i see that the receiver only gets the first chunk and displays a partial image, where is the error in combining the chunks?

  7. has anybody a example of sending chunks and combining chunks with tcpsocket?

  8. shao s

    is not verified Sep 14 Sudbury, Ontario, Canada
    Edited 2 months ago

    When sending data, you're best to delimit it somehow.. Seeing as you're sending binary data, EOT might appear in the data, so you'd either need to convert to non-binary (base64, etc) but this adds overhead and makes the file larger, or you would need to encapsulate the data (wrap it in JSON, etc) or prepend a length marker.. Whichever method you choose, when you receive the data, you just appending it to a variable and then when you receive the whole thing, you can do your parsing..

    Create a sub-class of the TCPSocket, add a private instance variable (I just call mine mBuffer)
    So in the DataReceived event just keep adding the new data to the buffer variable

    me.mBuffer = me.mBuffer + me.ReadAll()
    DIM offset As Integer = me.mBuffer.InStr(Chr(13) + Chr(10))  // I do this as a variable, as we need to do the lookup twice and if it's a huge file, it could be a performance hit
    
    if (offset > -1) then
      DIM pictureData As String = me.mBuffer.Left(offset)  // get the picture data
      DIM me.mBuffer = me.mBuffer.Right(offset + 2)  // delete the old picture data and take in account the CRLF combo
      // do the rest of your stuff here
    end if

    This was off the top of my head

  9. Thanks! But i just cannot receive any pic

    this is my code in the dataAvailable Event:

    me.mBuffer = me.mBuffer + me.ReadAll()
    DIM offset As Integer = me.mBuffer.InStr(Chr(13) + Chr(10)) 
    			
    if (offset > -1) then                        //doesn't that have to be in some kind of loop?
       DIM pictureData As String = me.mBuffer.Left(offset)  
       me.mBuffer = me.mBuffer.Right(offset + 2) 
      end if
    
     dim p as Picture
     p=Picture.FromData(me.mBuffer)
     window1.canvas1.Backdrop=p
     

    i just want to display the image when completed received...

  10. Dave S

    Sep 14 San Diego, California USA
    Edited 2 months ago
    dim p as Picture
     p=Picture.FromData(me.mBuffer)
     window1.canvas1.Backdrop=p

    this has to go in the DOWNLOADCOMPLETE event
    otherwise you are attempting to create a picture out of snippets of data, all of which are invalid picture data until you, well "have the whole picture" :D

    oh... and you need to store (concatenate) all the calls to DATAAVAILABLE

  11. the TCPSocket has no DOWNLOADCOMPLETE event...?

  12. Dave S

    Sep 14 San Diego, California USA

    This is true..... Since TCPSocket (my opinion) is more suited to communications streams (which have no specific end).....

    I was thinking (and always use) HTTPSocket or HTTPSecureSocket.... THOSE do, as they are more suited to downloading a file with a know size and end.

  13. so, please, anybody has a suggestion what i have to write to make my image diplayed when completely received?

  14. Dave S

    Sep 14 San Diego, California USA
    Edited 2 months ago

    ignore my suggestion... no worries

    I was thinking (and always use) HTTPSocket or HTTPSecureSocket.... THOSE do, as they are more suited to downloading a file with a know size and end.

  15. Edited 2 months ago

    no, i do not ignore your suggestions, i am thankful for every help ... but you're suggestion was based on HTTPSocket but i am using TCPSocket... and my solution (post 5) worked as long as the picture is small so i was hoping for a hint whats wrong with my code..

  16. Wayne G

    Sep 14 Pre-Release Testers, Xojo Pro New Zealand axisdirect.nz

    You are sending raw data to the client so your block terminator (boundary) is unsafe. Imagine a picture that has &c0D0Axx or &cxx0D0A to define a pixel. I would send the length of the block as the first two bytes then wait until the buffer (lookahead) contained the full block before processing it. You can detect EOF by the last block most likely being less than the defined block size or better send a block that is 1 byte with a value of &H00. For very large images you will need to add a block received response to the server so as to not overload the output buffer. Another issue that could come up is corruption of data in transit so sending an MD5 checksum for each block and for the entire image would also be prudent.

  17. Dave S

    Sep 14 San Diego, California USA

    @Marco W no, i do not ignore your suggestions, i am thankful for every help ... but you're suggestion was based on HTTPSocket but i am using TCPSocket... and my solution (post 5) worked as long as the picture is small so i was hoping for a hint whats wrong with my code..

    So you ARE ignoring my suggestion, which was to NOT use TCPSocket but use HTTPSocket.... but thats fine, its you app

  18. shao s

    is not verified Sep 14 Sudbury, Ontario, Canada
    me.mBuffer = me.mBuffer + me.ReadAll()
    DIM offset As Integer = me.mBuffer.InStr(Chr(13) + Chr(10)) 
    			
    if (offset > -1) then                        //doesn't that have to be in some kind of loop?
       DIM pictureData As String = me.mBuffer.Left(offset)  
       me.mBuffer = me.mBuffer.Right(offset + 2) 
    
      // do this when you have the full picture, so this needs to be inside the IF statement
     dim p as Picture
     p=Picture.FromData(me.mBuffer)
     window1.canvas1.Backdrop=p
    
    end if
    

or Sign Up to reply!