#1 2023-10-15 03:40:48

Flashcqxg
Member
Registered: 2018-01-11
Posts: 31

PDF:AddXObject is slow and out of memory!

My code is as follows, the image test.jpg is only 5kb in size. The program ran for more than 10 minutes, but did not receive the expected PDF file. Finally, it indicated that there was insufficient memory.
How can I improve it? Thank you!

var
  PDF: TPdfDocument;
  PDFPage: TPdfpage;
  SW: TStopwatch;
  I: Integer;
  FS: TFileStream;
  pdfImage: TPdfImage;
  BarCode: string;
  X, Y: Single;
begin
  SW := TStopwatch.StartNew;
  PDF := TPdfDocument.Create;
  FS := TFileStream.Create(ExtractFilePath(Application.ExeName) + 'output.pdf', fmCreate);
  try
    PDF.NewDoc;
    PDF.PDFA1 := True;
    PDF.DefaultPaperSize := psA4;
    PDF.SaveToStreamDirectBegin(FS);

    for I := 1 to 30000 do
    begin
      PDF.AddPage;
      BarCode := IdGenerator.NextId.ToString;
      pdfImage := TPdfImage.CreateJpegDirect(PDF, 'd:\test.jpg', True);
      PDF.AddXObject(BarCode, pdfImage);
      X := 200;
      Y := 800;
      PDF.Canvas.DrawXObject(X, Y, 30, 30, BarCode);
      pdfImage.ForceSaveNow;
      PDF.SaveToStreamDirectPageFlush(True);
    end;
    PDF.SaveToStreamDirectEnd;
    Memo1.Lines.Add(SW.ElapsedMilliseconds.ToString);
  finally
    PDF.Free;
    FS.Free;
  end;

Offline

#2 2023-10-15 12:29:38

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,700
Website

Re: PDF:AddXObject is slow and out of memory!

AFAIR SaveToStreamDirectPageFlush() and other functions work with the VCL canvas, not the PDF canvas.

So you need to use the TPdfDocumentGdi class and draw to the VclCanvas property.
To include the JPEG picture in the VclCanvas, use GdiCommentJpegDirect() function.

Offline

#3 2023-10-15 13:14:13

Flashcqxg
Member
Registered: 2018-01-11
Posts: 31

Re: PDF:AddXObject is slow and out of memory!

I test with the TPdfDocumentGdi , and set the i from 1 to 70000,it out of memory!

var
  // PDF: TPdfDocument;
  PDF: TPdfDocumentGDI;
  PDFPage: TPdfpage;
  SW: TStopwatch;
  I: Integer;
  FS: TFileStream;
  pdfImage: TPdfImage;
  BarCode: string;
  X, Y: Single;
  aRect: TRect;
begin
  SW := TStopwatch.StartNew;
  PDF := TPdfDocumentGDI.Create;
  // PDF := TPdfDocument.Create;
  FS := TFileStream.Create(ExtractFilePath(Application.ExeName) + 'output.pdf', fmCreate);
  try
    PDF.NewDoc;
    PDF.PDFA1 := True;
    PDF.DefaultPaperSize := psA4;
    PDF.SaveToStreamDirectBegin(FS);
    aRect := Rect(Point(20, 40), Point(60, 80));
    for I := 1 to 70000 do
    begin
      PDF.AddPage;
      BarCode := IdGenerator.NextId.ToString;
      GDICommentJpegDirect(PDF.VCLCanvas.Handle, 'd:\test.jpg', aRect);
      PDF.SaveToStreamDirectPageFlush(True);
    end;
    PDF.SaveToStreamDirectEnd;
    Memo1.Lines.Add(SW.ElapsedMilliseconds.ToString);
  finally
    PDF.Free;
    FS.Free;
  end;

Offline

#4 2023-10-15 13:38:12

rvk
Member
Registered: 2022-04-14
Posts: 115

Re: PDF:AddXObject is slow and out of memory!

Flashcqxg wrote:

I test with the TPdfDocumentGdi , and set the i from 1 to 70000,it out of memory!

With the latest version of mormot2.ui.pdf your code works fine for me (in Delphi 10.2 and 32 bit app) and results in a pdf of 25MB with 70.000 pages.
So you might want to use the latest version (the mormot2 one, not the synpdf one).

Offline

Board footer

Powered by FluxBB