#1 2023-08-03 13:03:46

mrsw
Member
Registered: 2019-09-06
Posts: 6

Add image to a page in a parallel task

Hi,
I am developing an application for convertion of a bounce of image files in pdf files, each image must represent a pdf page.

The code I wrote is:

          LPDFDocument := TPDFDocument.Create(True, 0, pdfa2A);
          LPDFDocument.DefaultPageLandscape := False;
          LPDFDocument.DefaultPaperSize := psA3;
          LPDFDocument.Info.Title := 'Simple PDF document';
          LPDFDocument.Info.CreationDate := Now;
          LPDFDocument.Info.Creator := 'My PDF converter app';

          LPicture := TSynPicture.Create;

          try
            for I := 0 to FSelectedFiles.Count - 1 do
            begin
              LFileName := FSelectedFiles[I];
              LPicture.LoadFromFile(LFileName);

              LPDFPage := LPDFDocument.AddPage;
              LPDFDocument.CreateBookMark(0, 'Page ' + IntToStr(I));
              LPDFDocument.CreateOutline('Page ' + IntToStr(I), 0, 0);
              LPDFImage := TPdfImage.Create(LPDFDocument, LPicture, True);
              LPDFDocument.AddXObject('Page' + IntToStr(I), LPDFImage);
              LPDFDocument.Canvas.DrawXObject(0,0, LPDFPage.PageWidth, LPDFPage.PageHeight, 'Page' + IntToStr(I));
            end;

            LPDFDocument.SaveToFile(FDestinationFileName);

If this code is execute in the main thread of the application it works perfectly, if executed in a parallel task it hang to DrawXObject line.
All the objects are created in the executing task.
If I comment AddXObject and DrawXObject lines the code works and the result is a PDF file with blank pages.

Where I'm wrong?
How can I make the code thread safe?

I can send a sample app reproducing the problem.

I'm using Delphi version 11.2 and mORMot2 from GitHub.

Thanks.

Last edited by mrsw (2023-08-03 15:24:20)

Offline

#2 2023-08-03 19:41:41

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

Re: Add image to a page in a parallel task

The mORMot PDF engine itself is thread safe.
But TSynPicture is based on GDI+ so is not thread safe.

You need either
- to protect your code with a critical section, i.e. Gdip.Lock/UnLock
- or use a direct Jpeg insertion without TSynPicture, i.e. TPdfImage.CreateJpegDirect.

Offline

#3 2023-08-04 08:55:14

mrsw
Member
Registered: 2019-09-06
Posts: 6

Re: Add image to a page in a parallel task

Do you means something like this?
Or there is a Gdip.Lock already available?
Sorry, I never used GDI+ before.

          try
            for I := 0 to FSelectedFiles.Count - 1 do
            begin
              LFileName := FSelectedFiles[I];
              LPicture.LoadFromFile(LFileName);

              LPDFPage := LPDFDocument.AddPage;
              LPDFDocument.CreateBookMark(0, 'Page ' + IntToStr(I));
              LPDFDocument.CreateOutline('Page ' + IntToStr(I), 0, 0);

              CritialSection.Acquire

              try
                LPDFImage := TPdfImage.Create(LPDFDocument, LPicture, True);
                LPDFDocument.AddXObject('Page' + IntToStr(I), LPDFImage);
                LPDFDocument.Canvas.DrawXObject(0,0, LPDFPage.PageWidth, LPDFPage.PageHeight, 'Page' + IntToStr(I));
              finally
                CriticalSection.Release;
              end;
            end;

            LPDFDocument.SaveToFile(FDestinationFileName);

Offline

Board footer

Powered by FluxBB