delphi,用indy10从客户端发送映像到服务器

时间:2013-05-17 10:47:03

标签: delphi sockets tcp indy10

我如何从Timage(客户端)发送到另一个Timage(服务器端)? 我正在使用delphi XE3和idtcpclient1,idtcpserver1(indy10组件)。 我已经尝试过做一些事情,但我遇到了一些麻烦。

服务器端:

FileStream := TFileStream.Create('ciao.jpg', fmCreate);
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.ReadStream(FileStream); FileStream.Free;
image1.Picture.LoadFromFile(sname);

客户端:

idTCPClient1.IOHandler.LargeStream := True;
FileStream := TFileStream.Create('hello.jpg', fmOpenRead);
IdTCPClient1.IOHandler.Write(FileStream,0,true);
filestream.Free;

2 个答案:

答案 0 :(得分:3)

传输不同图形格式的示例实现。

主要问题是您必须创建一个合适的GraphicClass 如果从文件加载图像,则从文件扩展名确定类 在此实现中,我们将信息添加到流中。

unit Unit1;
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, IdContext, Vcl.ExtCtrls, IdTCPConnection, IdTCPClient, IdBaseComponent,
  IdComponent, IdCustomTCPServer, IdTCPServer, Vcl.StdCtrls, Vcl.Imaging.jpeg;

type
  TForm1 = class(TForm)
    IdTCPServer1: TIdTCPServer;
    IdTCPClient1: TIdTCPClient;
    Source: TImage;
    Dest: TImage;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure IdTCPServer1Execute(AContext: TIdContext);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation
uses PNGImage;

{$R *.dfm}

//Enable transfer of different graphicformats

procedure Picture2Stream(DestStream: TMemoryStream; Picture: TPicture);
var
  ms2: TMemoryStream;
  TheClassName: AnsiString;
  len: Byte;
begin
  TheClassName := Picture.Graphic.ClassName;
  len := Length(TheClassName);
  DestStream.WriteBuffer(len, 1);
  if len > 0 then     // save GraphicClass name
    DestStream.WriteBuffer(TheClassName[1], len);
  ms2 := TMemoryStream.Create;
  try                // save graphic
    Picture.Graphic.SaveToStream(ms2);
    ms2.Position := 0;
    if ms2.Size > 0 then
      DestStream.CopyFrom(ms2, ms2.Size);
  finally
    ms2.Free;
  end;
end;

Procedure LoadPictureFromStream(Picture: TPicture; SourceStream: TMemoryStream);
var
  ms2: TMemoryStream;
  len: Byte;
  TheClassName: AnsiString;
  Graphic: TGraphic;
  GraphicClass: TGraphicClass;
begin
  SourceStream.Position := 0;
  SourceStream.ReadBuffer(len, 1);
  SetLength(TheClassName, len);
  if len > 0 then    // read GraphicClass name
    SourceStream.ReadBuffer(TheClassName[1], len);
  GraphicClass := TGraphicClass(FindClass(TheClassName)); //(*)
  if (GraphicClass <> nil) and (len > 0) then
  begin
    Graphic := GraphicClass.Create;  // create appropriate graphic class
    try
      ms2 := TMemoryStream.Create;
      try
        ms2.CopyFrom(SourceStream, SourceStream.Size - len - 1);
        ms2.Position := 0;
        Graphic.LoadFromStream(ms2);
      finally
        ms2.Free;
      end;
      Picture.Assign(Graphic);
    finally
      Graphic.Free;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    Picture2Stream(ms, Source.Picture);
    ms.Position := 0;
    IdTCPClient1.Host := '127.0.0.1';
    IdTCPClient1.Port := 12345;
    IdTCPClient1.Connect;
    IdTCPClient1.IOHandler.LargeStream := true;
    IdTCPClient1.IOHandler.Write(ms, ms.Size, true);
  finally
    ms.Free;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  IdTCPServer1.DefaultPort := 12345;
  IdTCPServer1.Active := true;
  ReportMemoryLeaksOnShutDown := true;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
var
  ms: TMemoryStream;
begin
  ms := TMemoryStream.Create;
  try
    AContext.Connection.IOHandler.LargeStream := true;
    AContext.Connection.IOHandler.ReadStream(ms);
    TThread.Synchronize(nil,
      Procedure
      begin
        LoadPictureFromStream(Dest.Picture, ms);
      end);
  finally
    ms.Free;
  end;
end;

initialization
// RegisterClasses to enable FindClass (*)
RegisterClasses([TIcon, TMetafile, TBitmap, TJPEGImage, TPngImage]);

end.

答案 1 :(得分:1)

你的问题不清楚,但似乎你正试图将一个'TImage'的内容(在客户端上)转移到服务器上的TImage。不过,目前还不清楚你是指一个图像文件还是一个实际的TImage。我要将“在客户端上的TImage中显示的图片”发送到服务器。 您可以使用TMemoryStream代替TFileStream。如果您真的想发送TImage.Picture中显示的图像,您可以执行以下操作(未经测试):

// Server side
var
  Jpg: TJpegImage;
begin
  Strm := TMemoryStream.Create;
  try
    Strm.Position := 0;
    AContext.Connection.IOHandler.LargeStream := True;
    AContext.Connection.IOHandler.ReadStream(Strm);
    Strm.Position := 0;
    Jpg := TJpegImage.Create;
    try
      Jpg.LoadFromStream(Strm);
      Image1.Picture.Assign(Jpg);
    finally
      Jpg.Free;
    end;
  finally
    Strm.Free;
  end;
end;

// Client side
IdTCPClient1.IOHandler.LargeStream := True;
Strm := TMemoryStream.Create;
try
  Image1.Picture.Graphic.SaveToStream(Strm);
  Strm.Position := 0;
  IdTCPClient1.IOHandler.Write(Strm, 0, True);
finally
  Strm.Free;
end;

如果这不是您想要的,编辑您的问题,以便我们了解您的目标。 (请勿在评论中告诉我们,但实际上要编辑您的问题以使其更清晰。)