DrawToIXCPage

PDF-XChange Editor SDK for Developers

Moderators: TrackerSupp-Daniel, Tracker Support, Paul - Tracker Supp, Vasyl-Tracker Dev Team, Chris - Tracker Supp, Sean - Tracker, Ivan - Tracker Software, Tracker Supp-Stefan

Forum rules
DO NOT post your license/serial key, or your activation code - these forums, and all posts within, are public and we will be forced to immediately deactivate your license.

When experiencing some errors, use the IAUX_Inst::FormatHRESULT method to see their description and include it in your post along with the error code.
Post Reply
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

DrawToIXCPage

Post by jeffp »

Below is my code using your DrawToIXPage call. In the old DLLs it seems to render much faster. Are there any IPXC_PageRenderParams or IPXC_OCCContext flags I can set to make the rendering of the page image go any faster?

Thanks.

Code: Select all

function PDF_CreateIXCPageFromPage(APage: IPXC_Page; ASize: Integer; var ADPI: Integer): IIXC_Page;
var
  AWidth, AHeight: Double;
  W, H: Cardinal;
  ADestRect: tagRECT;
  APageMatrix: PXC_Matrix;
  AFlags: Integer;
  ARenderParams: IPXC_PageRenderParams;
  AOCContext: IPXC_OCContext;
begin
  //Get Page dimensions in Points
  APage.GetDimension(AWidth, AHeight);

  //Make Sure the Image is not Too Big
  if (AHeight > AWidth) then
  begin
    if (P2X(AHeight, 100) > 4400) or (P2X(AWidth, 100) > 3400) then ADPI := 100;
  end else
  begin
    if (P2X(AWidth, 100) > 4400) or (P2X(AHeight, 100) > 3400) then ADPI := 100;
  end;

  //Convert to Pixes
  ADPI := Max(100, ADPI);
  W := Round(P2X(AWidth, ADPI));
  H := Round(P2X(AHeight, ADPI));

  if (ASize <= 0) then ASize := Max(H, W);

  if (H > W) then
  begin
    W := Ceil(ASize * (W / H));
    H := ASize;
  end else
  begin
    H := Ceil(ASize * (H / W));
    W := ASize;
  end;

  with ADestRect do
  begin
    Left := 0;
    Top := 0;
    Right := W;
    Bottom := H;
  end;

  //Defaults
  AFlags := DDF_AsVector;
  ARenderParams := nil;
  AOCContext := nil;
  APageMatrix := PDF_GetPageMatrix(APage, ADestRect);

  INST_IXC.Page_CreateEmpty(W, H, PageFormat_8RGB, 255, Result);   //PageFormat_8RGB, PageFormat_1Indexed
  APage.DrawToIXCPage(Result, ADestRect, APageMatrix, ARenderParams, AOCContext, nil);
end;
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: DrawToIXCPage

Post by Sasha - Tracker Dev Team »

Hello Jeff,

We'll need additional information:
1) Which DLL (version) were you using?
2) What do you mean "render much faster"? Can you give us some time equivalents?
3) Also, we'll need the document that you were testing - if it contains sensitive information - please mail it to polaringu@tracker-software.com

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: DrawToIXCPage

Post by jeffp »

Let me ask you this then: in your opinion what would be the fastest way to convert a large PDF file with say 1000+ pages into individual TIFF files, one TIFF file for each PDF page? I need the TIFFs at 300dpi.

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: DrawToIXCPage

Post by Sasha - Tracker Dev Team »

Hello Jeff,

The thing is, we don't know whether your code was changed or what is causing this behavior just from the piece of code and the information you provided. We don't know what DPI values were used before and after the tests you've done. Maybe, you were using the 100 dpi and then tested with 300. Also, we do not know, how you write the image on disk. Shortly speaking, you haven't answered my questions - so I can't possibly advice further with the information available.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: DrawToIXCPage

Post by jeffp »

Below is all the code you should need. It all starts with the MyTest procedure below. ASize = 0 means I want the image to be the dimensions of the actual page.

Here is my test file. It is really large so I'm giving you a link

http://www.lucion.com/files/DrawPage.zip

This memory usage seems to be fine. It grows but then levels off.

My big issue is that your older DLL call to PXCV_DrawPageToDC was about twice as fast as my code below using IPXC_Page.DrawToIXCPage

Code: Select all



function PDF_CreateIXCPageFromPage(APage: IPXC_Page; ASize: Integer; var ADPI: Integer): IIXC_Page;
var
  AWidth, AHeight: Double;
  W, H: Cardinal;
  ADestRect: tagRECT;
  APageMatrix: PXC_Matrix;
  ARenderParams: IPXC_PageRenderParams;
  AOCContext: IPXC_OCContext;
begin
  //Get Page dimensions in Points
  APage.GetDimension(AWidth, AHeight);

  //Make Sure the Image is not Too Big
  if (AHeight > AWidth) then
  begin
    if (P2X(AHeight, 100) > 4400) or (P2X(AWidth, 100) > 3400) then ADPI := 100;
  end else
  begin
    if (P2X(AWidth, 100) > 4400) or (P2X(AHeight, 100) > 3400) then ADPI := 100;
  end;

  //Convert to Pixes
  ADPI := Max(100, ADPI);
  W := Round(P2X(AWidth, ADPI));
  H := Round(P2X(AHeight, ADPI));

  if (ASize <= 0) then ASize := Max(H, W);

  if (H > W) then
  begin
    W := Ceil(ASize * (W / H));
    H := ASize;
  end else
  begin
    H := Ceil(ASize * (H / W));
    W := ASize;
  end;

  with ADestRect do
  begin
    Left := 0;
    Top := 0;
    Right := W;
    Bottom := H;
  end;

  //Defaults
  ARenderParams := nil;
  AOCContext := nil;
  APageMatrix := PDF_GetPageMatrix(APage, ADestRect);

  INST_IXC.Page_CreateEmpty(W, H, PageFormat_8RGB, 255, Result);   //PageFormat_8RGB, PageFormat_1Indexed, PageFormat_Vector
  APage.DrawToIXCPage(Result, ADestRect, APageMatrix, ARenderParams, AOCContext, nil);
end;

function IMG_PageToBitmap(APage: IIXC_Page; ASize: Integer = 0): TBitmap;
var
  W, H: Cardinal;
  ADestRect, ASrcRect: tagRECT;
  AScaleMethod: IXC_ScaleMethod;
begin
  Result := TBitmap.Create;
  Result.PixelFormat := pf24bit;
  APage.Get_Width(W);
  APage.Get_Height(H);

  with ASrcRect do
  begin
    Left := 0;
    Top := 0;
    Right := W;
    Bottom := H;
  end;

  if (ASize <= 0) then ASize := Max(H, W);

  if (H > W) then
  begin
    W := Ceil(ASize * (W / H));
    H := ASize;
  end else
  begin
    H := Ceil(ASize * (H / W));
    W := ASize;
  end;

  Result.SetSize(W, H);

  with ADestRect do
  begin
    Left := 0;
    Top := 0;
    Right := W;
    Bottom := H;
  end;

  if (ASrcRect.right = ADestRect.right) then
  begin
    APage.DrawToDC(Result.Canvas.Handle, 0, 0, W, H, 0, 0, DrawFlags_FillBackGround);  //DrawFlags_FillBackGround = 1, DrawFlags_UseTransparentColor = 2,
  end else
  begin
    //RULE OF THUMB: Use ScaleMethod_Bilinear to Shrink and ScaleMethod_Bicubic to Enlarge
    if (ASrcRect.right >= ADestRect.right) then AScaleMethod := ScaleMethod_Bilinear else AScaleMethod := ScaleMethod_Bicubic;
    APage.StretchDraw(Result.Canvas.Handle, ADestRect, ASrcRect, AScaleMethod, DrawFlags_FillBackGround);
  end;
end;


function PDF_CreateBitmapFromPage(APage: IPXC_Page; ASize: Integer; var ADPI: Integer): TBitmap;
var
  AIXCPage: IIXC_Page;
begin
  Result := nil;
  AIXCPage := PDF_CreateIXCPageFromPage(APage, ASize, ADPI);
  if Assigned(AIXCPage) then
  begin
    Result := IMG_PageToBitmap(AIXCPage);
    AIXCPage := nil;
  end;
end;


procedure MyTest;
var
  i, ADPI: Integer;
  ADir, AInput: String;
  ADoc: IPXC_Document;
  APage: IPXC_Page;
  APageCount: Cardinal;
  B: TBitmap;
begin
  ADir := ExtractFilePath(Application.ExeName) + 'Outputs\';
  AInput := ADir + 'DrawPage.pdf';
  ADPI := 300;

  ADoc := INST_PXC.OpenDocumentFromFile(PChar(AInput), nil, nil, 0, 0);
  ADoc.Pages.Get_Count(APageCount);

  for i := 0 to APageCount - 1 do
  begin
    ADoc.Pages.Get_Item(i, APage);
    B := PDF_CreateBitmapFromPage(APage, 0, ADPI);
    APage := nil;

    if Assigned(B) then
    try
      B.SaveToFile(ADir + 'DrawPage' + IntToStr(i + 1) + '.bmp');
    finally
      B.Free;
    end;
  end;
end;

And here is the main part of the older code I was using before your new DLLs

Code: Select all


procedure TPDFViewer.BuildPageBitmap(var B: TBitmap; APage, ASize: Integer;
  var ADPI: Integer; AUseVector: Boolean = False);
var
  AParams: PXV_CommonRenderParameters;
  hr: HRESULT;
  AWidth, AHeight: Double;
  W, H: Integer;
  AWholePage: TRect;
begin
  //PIXEL FORMAT: Must set correct format before passing B into this procedure
  //The default is pfDevice which makes file sizes huge; must change
  if (B.PixelFormat = pfDevice) then B.PixelFormat := pf24bit;

  PXCV_GetPageDimensions(FDocID, APage - 1, @AWidth, @AHeight); //Sizes are in Points

  //Make Sure the Image is not Too Big
  if (AHeight > AWidth) then
  begin
    if (P2X(AHeight, 100) > 4400) or (P2X(AWidth, 100) > 3400) then ADPI := 100;
  end else
  begin
    if (P2X(AWidth, 100) > 4400) or (P2X(AHeight, 100) > 3400) then ADPI := 100;
  end;

  ADPI := Max(100, ADPI);
  W := Round(P2X(AWidth, ADPI));  //Convert to Pixels
  H := Round(P2X(AHeight, ADPI)); //Convert to Pixels

  if (ASize <= 0) then ASize := Max(H, W);

  if (H > W) then
  begin
    W := Ceil(ASize * (W / H));
    H := ASize;
  end else
  begin
    H := Ceil(ASize * (H / W));
    W := ASize;
  end;

  with AWholePage do
  begin
    Left := 0;
    Top := 0;
    Right := Left + W;
    Bottom := Top + H;
  end;

  B.SetSize(W, H);

  AParams.WholePageRect := @AWholePage;
  AParams.DrawRect := nil;
	AParams.RenderTarget := pxvrm_Exporting; //pxvrm_Exporting, pxvrm_Viewing, pxvrm_Printing
  AParams.Flags := 0;
  if AUseVector then AParams.Flags := pxvrpf_UseVectorRenderer;

  //CRITICAL: Must use B.Canvas.Handle NOT B.Handle
  hr := PXCV_DrawPageToDC(FDocID, APage - 1, B.Canvas.Handle, @AParams);

  PXCV_ReleaseCachedData(FDocID, pxvrcd_ReleaseDocumentImages + pxvrcd_ReleaseDocumentFonts + pxvrcd_ReleaseGlobalFonts);
end;
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: DrawToIXCPage

Post by Sasha - Tracker Dev Team »

Hello Jeff,

No wonder that everything is working much slower - you are doing several unneeded conversions.
What you need to do is use the IIXC_Image to write on disk not the Bitmap conversion.

Code: Select all

//PDFXEdit.IIXC_Page iPage
iPage.ClearFormatParams();
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_FORMAT, (uint)PDFXEdit.IXC_ImageFileFormatIDs.FMT_TIFF_ID);
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_ITYPE, 0); //0 - Auto, 10 - Grayscale 16 - TrueColor (for different values look in the ImagesTest utility)
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_COMP_TYPE, (uint)PDFXEdit.IXC_ImageFileCompressionTypes.IComp_Default);
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_XDPI, 300);
iPage.set_FmtInt((uint)PDFXEdit.IXC_FormatParametersIDS.FP_ID_YDPI, 300);
PDFXEdit.IIXC_Image tmpImg = iInst.CreateEmptyImage();
tmpImg.InsertPage(iPage);
tmpImg.Save(@"D:\Test.tif", PDFXEdit.IXC_CreationDisposition.CreationDisposition_Overwrite);
The ImagesTest utility is available here:
https://forum.pdf-xchange.com/ ... 66&t=25943
You can use it to further modify the output format.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: DrawToIXCPage

Post by jeffp »

The slowness is in the call to

Code: Select all

APage.DrawToIXCPage(Result, ADestRect, APageMatrix, ARenderParams, AOCContext, nil);
All the IIXC_Page conversion stuff to TBitmap is fast. Plus I need as an end result a TBitmap not a file on disk.

--Jeff
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: DrawToIXCPage

Post by Sasha - Tracker Dev Team »

Hello Jeff,

If you need that Bitmap then you can skip the IIXC_Page part and better use the https://sdkhelp.pdf-xchange.com/vie ... awToDevice method. With the help of this, you will draw on the bitmap's hDC directly.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: DrawToIXCPage

Post by jeffp »

I understand that. I have also tried the IPXC_Page.DrawToDeivce call.

What I'm saying is that the slowness is in the calls to

IPXC_Page.DrawToIXCPage

and

IPXC_Page.DrawToDevice

They are both much slower than the call to the old PXCV_DrawPageToDC.

What I'm asking is is there anything is how I've setup the new calls that would account for that?

--Jeff
User avatar
Lzcat - Tracker Supp
Site Admin
Posts: 677
Joined: Thu Jun 28, 2007 8:42 am

Re: DrawToIXCPage

Post by Lzcat - Tracker Supp »

Hi Jeff.
Have you any timings? Also, which files are you using for testing and which settings?
There should be no slowdown in new code, so looks like something else is changed too.
Victor
Tracker Software
Project manager

Please archive any files posted to a ZIP, 7z or RAR file or they will be removed and not posted.
jeffp
User
Posts: 914
Joined: Wed Sep 30, 2009 6:53 pm

Re: DrawToIXCPage

Post by jeffp »

Let me setup a test project and diagnose it a bit more on my end.
Sasha - Tracker Dev Team
User
Posts: 5522
Joined: Fri Nov 21, 2014 8:27 am
Contact:

Re: DrawToIXCPage

Post by Sasha - Tracker Dev Team »

We'll wait for your sample project then.

Cheers,
Alex
Subscribe at:
https://www.youtube.com/channel/UC-TwAMNi1haxJ1FX3LvB4CQ
Post Reply