拉撒路 TImage 到 Base64

Lazarus TImage to Base64

我正在尝试将 TImage 图片编码为 base64 以进行剩余传输,我尝试了几种方法,但似乎无法将其编码为字符串。这就是我现在拥有的:

      imgstream := TStringStream.Create('');
      OutputStream := TStringStream.Create('');
      Encoder := TBase64EncodingStream.Create(OutputStream);
      try
        image1.Picture.SaveToStream(imgstream);
        Encoder.CopyFrom(imgstream, imgstream.Size);

        showmessage(OutputStream.DataString);
      finally
        imgstream.Free;
        Encoder.Free;
        OutputStream.Free;
      end;

现在它给了我一个例外。当我 showmessage(imgstream.DataString) 我得到一个奇怪的 BM6~ 字符串。

CopyFrom 之前添加 imgstream.Position := 0; 之后,现在我得到的数据为空白,无一例外:

TBase64EncodingStream不适合大二进制转换,我是说,会很慢,还有Image1.Picture.SaveToStream,默认会把图片保存成Bitmap格式,所以会很慢大。尝试使用 JPG 格式。

procedure TForm1.Button1Click(Sender: TObject);
var
  imgstream, Outputstream: TStream;
  Encoder: TBase64EncodingStream;
  jpg: TJPEGImage;
  I: Int64;
begin
  I := GetTickCount64;
  imgstream := TMemoryStream.Create();
  Outputstream := TStringStream.Create('');
  jpg := TJPEGImage.Create;
  Encoder := TBase64EncodingStream.Create(Outputstream);
  try
    jpg.Assign(Image1.Picture.Bitmap);
    jpg.CompressionQuality:=75;
    jpg.SaveToStream(imgstream);
    imgstream.Position:= 0;
    Encoder.CopyFrom(TStringStream(imgstream), imgstream.Size);
    Encoder.Flush;
    Memo1.Text:='data:image/jpg;base64,'+ TStringStream(Outputstream).DataString;
    ShowMessage('Created in '+IntToStr(GetTickCount64-I)+'ms');
  finally
    imgstream.Free;
    Encoder.Free;
    Outputstream.Free;
    jpg.Free;
  end;
end;         

为了改进编码,也许您可​​以尝试使用线程将二进制文件分成 3 的倍数块来处理每个块,并在最后加入处理过的编码块。

例如使用 4 个线程,硬编码。

{ TEncodeThread }

  TEncodeThread = class (TThread)
  private
    fForm: TForm1;
    fStream: TStream;
    fStatusText: String;
    procedure ShowStatus;
  protected
    procedure Execute; override;
  public
    constructor Create(CreateSuspended:Boolean; const AForm: TForm1);
    procedure SetStream(const AStream: TStream);
  end;   

...
procedure TForm1.Button3Click(Sender: TObject);
var
  jpg: TJPEGImage;
  mul3: Int64;
  mod3: Int64;
  dif3: Int64;
  imgstream: TStringStream;
begin
  Steps:=0;
  Start:=GetTickCount64;
  imgstream := TStringStream.Create('');
  jpg := TJPEGImage.Create;
  try
    jpg.Assign(Image1.Picture.Bitmap);
    jpg.CompressionQuality:=75;
    jpg.SaveToStream(imgstream);

    mul3 := imgstream.Size div 4;
    mod3 := mul3 mod 3;
    if mod3 <> 0 then
       mul3 := mul3 + 3 - mod3;
    dif3 := imgstream.Size - mul3*4;
    memo1.text := 'Total Size: '+ IntToStr(imgstream.size)
    + #13'Part1: '+IntToStr(mul3)
    + #13'Part2: '+IntToStr(mul3)
    + #13'Part3: '+IntToStr(mul3)
    + #13'Part4: '+IntToStr(mul3+dif3)
    + #13'Rest: '+IntToStr(dif3);

    Part1.Position:=0;
    Part2.Position:=0;
    Part3.Position:=0;
    Part4.Position:=0;
    imgstream.Position:=0;
    Part1.CopyFrom(imgstream,mul3);
    Part2.CopyFrom(imgstream,mul3);
    Part3.CopyFrom(imgstream,mul3);
    Part4.CopyFrom(imgstream,mul3+dif3);

    Thr1 := TEncodeThread.Create(True, Self);
    Thr2 := TEncodeThread.Create(True, Self);
    Thr3 := TEncodeThread.Create(True, Self);
    Thr4 := TEncodeThread.Create(True, Self);

    Thr1.SetStream(Part1);
    Thr1.Start;
    Thr2.SetStream(Part2);
    Thr2.Start;
    Thr3.SetStream(Part3);
    Thr3.Start;
    Thr4.SetStream(Part4);
    Thr4.Start;

  finally
    imgstream.Free;
    jpg.Free;
  end;
end;

procedure TEncodeThread.Execute;
var
  Encoder: TBase64EncodingStream;
  buf: TStream;
begin

    buf := TStringStream.Create('');
    Encoder := TBase64EncodingStream.Create(buf);
    try
      fStream.Position:= 0;
      Encoder.CopyFrom(TStringStream(fStream), fStream.Size);
      Encoder.Flush;
      buf.Position:= 0;
      fForm.Out1.CopyFrom(TStringStream(buf), buf.Size);
      Inc(fForm.Steps);
      if fForm.Steps = 3 then
      begin
        fForm.Out1.Position:=0;
        fForm.Out2.Position:=0;
        fForm.Out3.Position:=0;
        fForm.Out4.Position:=0;
        fForm.Memo1.Text:='data:image/jpg;base64,'
        + TStringStream(fForm.Out1).DataString
        + TStringStream(fForm.Out2).DataString
        + TStringStream(fForm.Out3).DataString
        + TStringStream(fForm.Out4).DataString;
      end;


    finally
      Encoder.Free;
      buf.Free;
    end;


end;     

这个演示并没有真正优化,也没有正确同步(输出可能格式错误),但是,作为一个起点它可能会有所帮助。 zipped project