从memorystream读取多个位图

时间:2014-08-11 10:10:39

标签: delphi

我需要一些关于Delphi位图和内存流的帮助。 我只是摆弄Debenu PDF库,应该将pdf页面呈现给BMP,然后再将它们读回Image组件:

var  
    Image1: TImage;
    Image2: TImage;   
    PDF: TDebenuPDFLibrary;
    MS: TMemoryStream;

procedure TForm1.Button1Click(Sender: TObject);
    begin
        PDF.LoadFromFile('D:/something.pdf','');
        MS:=TMemoryStream.Create;
        PDF.RenderPageToStream(72,1,0,MS);
        MS.Position:= 0; 
        Image1.Picture.Bitmap.LoadFromStream(MS);
        Image1.Repaint;
        MS.Free;
    end;

它有效,到目前为止一切顺利! 但是当我尝试加载多个图像时,我会得到运行时消息:

"Stream read error"

我尝试的代码:

var 
    Image1: TImage;
    Image2: TImage;   
    PDF: TDebenuPDFLibrary; //To render PDF to bitmaps
    MS: TMemoryStream;

procedure TForm1.Button1Click(Sender: TObject);
    begin
        PDF.LoadFromFile('D:/something.pdf','');
        MS:=TMemoryStream.Create;
        PDF.RenderPageToStream(72,1,0,MS); //First page
        PDF.RenderPageToStream(72,2,0,MS); //Second page
        MS.Position:= 0; 
        Image1.Picture.Bitmap.LoadFromStream(MS);
        Image1.Repaint;
        Image2.Picture.Bitmap.LoadFromStream(MS);
        Image2.Repaint;
        MS.Free;
    end;

任何帮助?

2 个答案:

答案 0 :(得分:1)

您遇到问题的最可能的解释是RenderPageToStream在写入之前寻找流的开头。可以将位图连接成一个流并通过连续调用TBitmap.LoadFromStream来读取它们,因此问题必须在于写入流的代码。因此RenderPageToStream可能是罪魁祸首。

如果是这样,并且应该很容易为程序添加一些诊断程序来检测这一点,那么您应该通过将每个图像放在一个单独的流中来解决问题。或者,重复使用相同的流,但不要尝试一次将多个图像放入其中。或者使用某种形式的复合存储将多个图像放在一个流中,如Remy的回答所示。

答案 1 :(得分:1)

如果要从单个源流加载多个图像,最好在分割流中的图像,然后为每个加载使用单独的流。这使得在流数据中非常清楚一个图像结束并且下一个图像开始。例如:

procedure RenderPDFToStream(PDF: TDebenuPDFLibrary; Page: Integer; Stream: TStream);
var
  MS: TMemoryStream;
  Size: Integer;
begin
  MS := TMemoryStream.Create;
  try
    PDF.RenderPageToStream(72, Page, 0, MS);
    Size := MS.Size;
    Stream.WriteBuffer(Size, SizeOf(Size));
    if Size > 0 then
      Stream.CopyFrom(MS, Size);
  finally
    MS.Free;
  end;
end;

procedure LoadBitmapFromStream(Stream: TStream; Bitmap: TBitmap);
var
  MS: TMemoryStream;
  Size: Integer;
begin
  MS := TMemoryStream.Create;
  try
    Stream.ReadBuffer(Size, SizeOf(Size));
    if Size > 0 then
      MS.CopyFrom(Stream, Size);
    MS.Position := 0;
    Bitmap.LoadFromStream(MS);
  finally
    MS.Free;
  end;
end;

var 
  Image1: TImage;
  Image2: TImage;   
  PDF: TDebenuPDFLibrary; //To render PDF to bitmaps

procedure TForm1.Button1Click(Sender: TObject);
var
  MS: TMemoryStream;
begin
  PDF.LoadFromFile('D:/something.pdf','');
  MS := TMemoryStream.Create;
  try
    RenderPDFToStream(PDF, 1, MS);
    RenderPDFToStream(PDF, 2, MS);
    MS.Position := 0; 
    LoadBitmapFromStream(MS, Image1.Picture.Bitmap);
    LoadBitmapFromStream(MS, Image2.Picture.Bitmap);
  finally
    MS.Free;
  end;
end;