Search code examples
delphitcpudpindy

Udp image streaming, delphi indy10


i'm using delphi xe4 with indy10 component and i want to send an image from an Tidudpclient to Tidudpserver. I already done this operation with tcp component,but the same code didn't work with udp. how i can do this? Thanks in advance!

Timage(client)--->streamUDP-->Timage(server)

CLIENT SIDE----------------------------------------------- SEND IMAGE

var
    pic: tbitmap;
       Strm : TMemoryStream;
        img2:Timage;

    buffer:TIdBytes;
    begin

        try
          img2:=Timage.Create(nil);
          pic:=Tbitmap.Create;
          Takekpic(pic);     
          BMPtoJPG(pic,img2);
          Strm := TMemoryStream.Create;
          img2.Picture.bitmap.SaveToStream(strm);
          Strm.Position:=0;
          ReadTIdBytesFromStream(Strm,buffer,SizeOf(Strm),0);
          IdTrivialFTPServer1.SendBuffer('192.168.17.128',1234,buffer);
        finally
             strm.Free;
          end; 
    end;

SERVER SIDE---------------------------------------------------- READ IMAGE

procedure TForm6.IdTrivialFTP1UDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
    var
Strm : TMemoryStream;
Jpg: TJpegImage;

begin
      Strm := TMemoryStream.Create;
      try    

         WriteTIdBytesToStream(Strm,AData,SizeOf(AData),0);
         strm.Position:=0;
         Jpg := TJpegImage.Create;
         jpg.LoadFromStream(Strm);  <---- error while reading (JPEG Error #53)
         img1.Picture.assign(jpg);
      finally
         strm.Free;
         Jpg.Free;
      end;
end;

what can be wrong in this code?


Solution

  • TIdUDPClient and TIdUDPServer do not support sending/receiving TStream data. You can save your image data into a TStream, but you will have to send/receive it using TIdBytes chunks.

    Alternatively, use TIdTrivialFTP and TIdTrivialFTPServer instead, which implement TFTP, a UDP-based file transfer protocol. They operate using TStream objects

    Update: for example:

    Client:

    var
      bmp: TBitmap;
      jpg: TJPEGImage;
      Strm : TMemoryStream;
    begin
      Strm := TMemoryStream.Create;
      try
        jpg := TJPEGImage.Create;
        try
          bmp := TBitmap.Create;
          try 
            Takekpic(bmp);     
            jpg.Assign(bmp);
          finally
            bmp.Free;
          end;
          jpg.SaveToStream(Strm);
        finally
          jpg.Free;
        end;
        Strm.Position := 0;
        {
        These can be assigned ahead of time...
        IdTrivialFTP1.Host := '192.168.17.128';
        IdTrivialFTP1.Port := 1234;
        }
        IdTrivialFTP1.Put(Strm, 'image.jpg');
      finally
        Strm.Free;
      end; 
    end;
    

    Server:

    procedure TForm6.IdTrivialFTPServer1WriteFile(Sender: TObject; var FileName: String; const PeerInfo: TPeerInfo; var GrantAccess: Boolean; var AStream: TStream; var FreeStreamOnComplete: Boolean) of object;
    begin
      if FileName = 'image.jpg' then
      begin
        GrantAccess := True;
        AStream := TMemoryStream.Create;
        FreeStreamOnComplete := True;
      end else
        GrantAccess := False;
    end;
    
    {
    If you set TIdTrivialFTPServer.ThreadedEvent to False, this event handler
    runs in the context of the main thread, so the UI can be accessed safely.
    If you set IdTrivialFTPServer.ThreadedEvent to True, this event handler
    runs in the context of a worker thread, so you will have to manually
    synchronize with the main thread when updating the UI...
    }
    procedure TForm6.IdTrivialFTPServer1TransferComplete(Sender: TObject; const Success: Boolean; const PeerInfo: TPeerInfo; var AStream: TStream; const WriteOperation: Boolean);
    var
      jpg: TJPEGImage;
    begin
      if WriteOperation and Success then
      begin
        jpg := TJPEGImage.Create;
        try
          AStream.Position := 0;
          jpg.LoadFromStream(AStream);
          img1.Picture.Assign(jpg);
        finally
          jpg.Free;
        end;
      end;
    end;