Convert BitMap to string without line breaks?

前端 未结 2 987
别跟我提以往
别跟我提以往 2020-12-11 10:50

Somewhere I found this code to convert a BitMap to a string:

function Base64FromBitmap(Bitmap: TBitmap): string;
var
  Input: TBytesStream;
  Output: TString         


        
相关标签:
2条回答
  • 2020-12-11 11:36

    XE7 introduces the System.NetEncoding unit which contains a base64 encoder. This is intended to be used rather than the encoder from Soap.EncdDecd.

    The constructor of TBase64Encoding has overloads that allow you to specify characters per line (and line break text). Unfortunately Embarcadero haven't deigned to provide documentation yet so we need to read the source to work out what exactly to pass. Having done that, it becomes clear that line breaks are inserted only if the number of characters per line is strictly positive. So create an encoding object like this:

    Encoding := TBase64Encoding.Create(0);
    

    Once you have a suitable encoding object use Encode to encode your stream of bytes to text. And Decode to reverse the process.

    That could look like this:

    function Base64FromBitmap(Bitmap: TBitmap): string;
    var
      Input: TBytesStream;
      Output: TStringStream;
      Encoding: TBase64Encoding;
    begin
      Input := TBytesStream.Create;
      try
        Bitmap.SaveToStream(Input);
        Input.Position := 0;
        Output := TStringStream.Create('', TEncoding.ASCII);
        try
          Encoding := TBase64Encoding.Create(0);
          try
            Encoding.Encode(Input, Output);
            Result := Output.DataString;
          finally
            Encoding.Free;
          end;
        finally
          Output.Free;
        end;
      finally
        Input.Free;
      end;
    end;
    
    procedure BitmapFromBase64(Base64: string; Bitmap: TBitmap);
    var
      Input: TStringStream;
      Output: TBytesStream;
      Encoding: TBase64Encoding;
    begin
      Input := TStringStream.Create(Base64, TEncoding.ASCII);
      try
        Output := TBytesStream.Create;
        try
          Encoding := TBase64Encoding.Create(0);
          try
            Encoding.Decode(Input, Output);
            Output.Position := 0;
            Bitmap.LoadFromStream(Output);
          finally
            Encoding.Free;
          end;
        finally
          Output.Free;
        end;
      finally
        Input.Free;
      end;
    end;
    

    Alternatively you can use EncodeBytesToString and DecodeStringToBytes. Which might look like this:

    function Base64FromBitmap(Bitmap: TBitmap): string;
    var
      Stream: TBytesStream;
      Encoding: TBase64Encoding;
    begin
      Stream := TBytesStream.Create;
      try
        Bitmap.SaveToStream(Stream);
        Encoding := TBase64Encoding.Create(0);
        try
          Result := Encoding.EncodeBytesToString(Copy(Stream.Bytes, 0, Stream.Size));
        finally
          Encoding.Free;
        end;
      finally
        Stream.Free;
      end;
    end;
    
    procedure BitmapFromBase64(Base64: string; Bitmap: TBitmap);
    var
      Stream: TBytesStream;
      Bytes: TBytes;
      Encoding: TBase64Encoding;
    begin
      Stream := TBytesStream.Create;
      try
        Encoding := TBase64Encoding.Create(0);
        try
          Bytes := Encoding.DecodeStringToBytes(Base64);
          Stream.WriteData(Bytes, Length(Bytes));
          Stream.Position := 0;
          Bitmap.LoadFromStream(Stream);
        finally
          Encoding.Free;
        end;
      finally
        Stream.Free;
      end;
    end;
    

    What would be really good would be if we could have something like the compression and decompression streams that are available with zlib. We could create an encoding stream, save the bitmap to it, and read out the base64 text. In the other direction we'd feed base64 text into a decoding stream, and then load the bitmap from it. This should really be part of the NetEncoding unit, but it would be simple enough to add as a class helper.

    0 讨论(0)
  • 2020-12-11 11:39

    Soap.EncdDecd.EncodeStream() is hard-coded to output a line break every 75 characters. The only way to change that is to make a copy of Soap.EncdDecd.pas, edit it, and then add the copy to your project (and this approach does not work if your project has Runtime Packages enabled).

    You can use Indy's TIdEncoderMIME class as an alternative. It does not output line breaks:

    uses
      ..., IdCoderMIME;
    
    function Base64FromBitmap(Bitmap: TBitmap): string;
    var
      Input: TMemoryStream;
    begin
      Input := TMemoryStream.Create;
      try
        Bitmap.SaveToStream(Input);
        Input.Position := 0;
        Result := TIdEncoderMIME.EncodeStream(Input);
      finally
        Input.Free;
      end;
    end;
    
    0 讨论(0)
提交回复
热议问题