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;