将位图转换为无换行符的字符串?

5

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

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;

然而,这会返回一个包含换行的块状文本。是否有可能获取一行没有换行符的单行文本?

2个回答

11
XE7引入了System.NetEncoding单元,其中包含一个base64编码器。这是用于替代Soap.EncdDecd编码器的。 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单元的一部分,但将其作为类助手添加也很简单。

David,根据您的建议,我已经添加了修改后的代码。这样输出的16 x 16像素位图字符数为1440个。有没有办法减少字符数? - user1580348
压缩是否也会降低质量? - user1580348
使用EncodeBytesToString会将输出字符串的大小从1440增加到10924个字符! - user1580348
好的,我写了一些代码来展示给你不同的选项。希望这足够了。 - David Heffernan
我认为我可以,但是当我说“简单”时,我的意思是“可行”。要做到完美需要付出很大的努力。 - David Heffernan
显示剩余8条评论

7

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;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接