【问题标题】:Convert BitMap to string without line breaks?将位图转换为没有换行符的字符串?
【发布时间】:2015-05-03 12:28:18
【问题描述】:

我在某处找到了将位图转换为字符串的代码:

function Base64FromBitmap(Bitmap: TBitmap): string;
var
  Input: TBytesStream;
  Output: TStringStream;
begin
  Input := TBytesStream.Create;
  try
    Bitmap.SaveToStream(Input);
    Input.Position := 0;
    Output := TStringStream.Create('', TEncoding.ASCII);
    try
      Soap.EncdDecd.EncodeStream(Input, Output);
      Result := Output.DataString;
    finally
      Output.Free;
    end;
  finally
    Input.Free;
  end;
end;

但是,这会返回一个换行块。是否有可能得到一个没有换行符的单行?

【问题讨论】:

    标签: delphi bitmap encode delphi-xe7


    【解决方案1】:

    XE7 引入了 System.NetEncoding 单元,其中包含一个 base64 编码器。这是打算使用的,而不是来自Soap.EncdDecd 的编码器。

    constructor of TBase64Encoding 具有允许您指定每行字符(和换行符文本)的重载。不幸的是,Embarcadero 还没有提供文档,所以我们需要阅读源代码来确定到底要传递什么。这样做之后,很明显只有当每行的字符数严格为正时才插入换行符。所以像这样创建一个编码对象:

    Encoding := TBase64Encoding.Create(0);
    

    一旦您有了合适的编码对象,请使用Encode 将您的字节流编码为文本。和Decode 来扭转这个过程。

    可能是这样的:

    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;
    

    您也可以使用EncodeBytesToStringDecodeStringToBytes。可能看起来像这样:

    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;
    

    如果我们可以拥有像 zlib 中可用的压缩和解压缩流之类的东西,那将是非常好的。我们可以创建一个编码流,将位图保存到其中,然后读出 base64 文本。在另一个方向,我们将 base64 文本输入解码流,然后从中加载位图。这确实应该是NetEncoding 单元的一部分,但添加为类帮助器会很简单。

    【讨论】:

    • 大卫,根据您的建议,我添加了更改后的代码。它是否正确?这将为 16 x 16 像素位图输出 1440 个字符。有没有办法减少字符数?
    • 1440 听起来不错,假设为 32bpp。如果您想减小尺寸,请压缩图像。
    • 压缩是否也会降低质量?
    • 取决于你怎么做。 PNG 不会。
    • 我认为您可以使用更少的流。一个字节流然后EncodeBytesToString 就可以了。
    【解决方案2】:

    Soap.EncdDecd.EncodeStream() 被硬编码为每 75 个字符输出一个换行符。改变它的唯一方法是复制Soap.EncdDecd.pas,对其进行编辑,然后将副本添加到您的项目中(如果您的项目启用了运行时包,则此方法不起作用)。

    您可以使用 Indy 的 TIdEncoderMIME 类作为替代方案。它不输出换行符:

    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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2012-02-06
      • 1970-01-01
      • 1970-01-01
      • 2015-01-06
      相关资源
      最近更新 更多