【问题标题】:delphi, send image with indy10 from client to serverdelphi,使用indy10将图像从客户端发送到服务器
【发布时间】:2013-05-17 10:47:02
【问题描述】:

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

服务器端:

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;

【问题讨论】:

  • “我已经尝试过做某事,但遇到了一些麻烦”。你试图做什么,你遇到了什么麻烦?请edit您的帖子并向我们展示您迄今为止尝试过的对您不起作用的方法。
  • 我使用了文件,我发送了一个文件并打开它,我需要一个方法来绕过这一步,现在是:Timage(client)->file->stream->file- >Timage(服务器)
  • 我想要 Timage(client)->stream->Timage(server)

标签: delphi sockets tcp indy10


【解决方案1】:

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

主要问题是您必须创建一个适当的 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.

【讨论】:

    【解决方案2】:

    您的问题不清楚,但您似乎正在尝试将一个“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;
    

    如果这不是您想要的,请编辑您的问题,以便我们了解您想要做什么。 (不要在 cmets 中告诉我们,而是实际编辑您的问题以使其更清楚。)

    【讨论】:

    • 你的答案很好,我需要什么!我会测试它,对不起我的问题
    • 我在Image1.Picture.Graphic.LoadFromStream(Strm); 期间出现错误我在地址 00b85e1a 处发生访问冲突...读取地址 0000000
    • 那是因为您之前从未分配过一个。我将进行编辑以提供解决方案。
    • 只有当Image.Picture.Graphic 在客户端是TJPEGImage 时,您的示例才有效,因为TJPEGImage 在服务器端使用。如果您需要支持多种图像格式,则客户端必须指定它正在传输的格式,以便服务器可以为其创建适当的TGraphic 类的实例。
    • Remy,原始问题中发布的代码专门在客户端和服务器端都使用了JPEG图像。我回答了所提出的具体问题。如果发布者对如何传输不同格式的图像并显示它们有额外的问题,那将是一个额外的问题。 :-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-07
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多