Search code examples
imagedelphistreamtransfer

Delphi :Transferring Image


Delphi 2010

I'm Transferring Image via custom TCP Socket control uses UTF-8

Client Side

var
TSS: TStringStream;
STR :String;
JPG:TJPEGImage;
BMP:TBitmap;
begin
Try
BMP.LoadFromFile('C:\1.bmp');

JPG.Assign(BMP);
JPG.CompressionQuality:=80;
JPG.Compress;

TSS:=TStringStream.Create;
JPG.SaveToStream(TSS);

STR:=TSS.DataString;

MyTCPSocket.SendString(STR);


finally
BMP.free;
JPG.free;
TSS.free;
end;
end;

Server Side

Var
TSS: TStringStream;

TSS:=TStringStream.Create;
TSS.WriteString(STR);
TSS.SaveToFile('C:\2.jpg');

This code working on the same pc great.

The problem when I send the image to other pc that uses different encoding it receive the image but I see many wrong characters in the data "?????"

I think when TStringStream writes the bytes to the file it fails to convert the unicode characters to bytes so it appears like "?"

Any idea is much appreciated


Solution

  • You are trying to send binary data as if it were UTF-8 encoded text. It is not, so do not try to do that! Send the binary data in its original binary form, eg:

    var
      MS: TMemoryStream;
      JPG: TJPEGImage;
      BMP: TBitmap;
    begin
      MS := TMemoryStream.Create;
      try
        JPG := TJPEGImage.Create;
        try
          BMP := TBitmap.Create;
          try
            BMP.LoadFromFile('C:\1.bmp');
            JPG.Assign(BMP);
          finally
            BMP.Free;
          end;
          JPG.CompressionQuality := 80;
          JPG.Compress;
          JPG.SaveToStream(MS);
        finally
          JPG.Free;
        end;
        MS.Position := 0;
        MyTCPSocket.SendStream(MS);
      finally
        MS.free;
      end;
    end;
    

    var
      MS: TMemoryStream;
    begin
      MS := TMemoryStream.Create;
      try
        MyTCPSocket.ReadStream(MS);
        MS.Position := 0;
        MS.SaveToFile('C:\2.jpg');
      finally
        MS.Free;
      end;
    end;
    

    If you must send binary data as text, you need to encode the data using a real binary-to-text encoding algorithm, such as base64 or yEnc, not UTF-8 (which is designed for only encoding Unicode text, not binary data), eg:

    // TIdEncoderMIME and TIdDecoderMIME are part of Indy,
    // which ships with Delphi, but you can use whatever
    // you want...
    

    uses
      ..., IdCoderMIME;
    
    var
      S: String;
      MS: TMemoryStream;
      JPG: TJPEGImage;
      BMP: TBitmap;
    begin
      MS := TMemoryStream.Create;
      try
        JPG := TJPEGImage.Create;
        try
          BMP := TBitmap.Create;
          try
            BMP.LoadFromFile('C:\1.bmp');
            JPG.Assign(BMP);
          finally
            BMP.Free;
          end;
          JPG.CompressionQuality := 80;
          JPG.Compress;
          JPG.SaveToStream(MS);
        finally
          JPG.Free;
        end;
        MS.Position := 0;
        S := TIdEncoderMIME.EncodeStream(MS);
      finally
        MS.free;
      end;
      MyTCPSocket.SendString(S);
    end;
    

    uses
      ..., IdCoderMIME;
    
    var
      S: string;
      MS: TMemoryStream;
    begin
      S := MyTCPSocket.ReadString;
      MS := TMemoryStream.Create;
      try
        TIdDecoderMIME.DecodeStream(S, MS);
        MS.Position := 0;
        MS.SaveToFile('C:\2.jpg');
      finally
        MS.Free;
      end;
    end;