PDFiumを使ってみたいのですが

88 views
Skip to first unread message

kuro_m...@yahoo.co.jp

unread,
Dec 11, 2024, 3:47:45 AM12/11/24
to radstu...@googlegroups.com

お世話になってます、黒川といいます


PDFファイルから指定ページのイメージ取得や記載内容をテキストで取得

できないかと、Delphi7でPDFiumを使ってみようとしているのですが、

ドキュメント及び指定ページの取得はできているように思えるのですが、

TBitmapに描画させてようとするとEAccessViolationになってしまいます。


呼び出し方が違うのでしょうか?


サンプルコードを記載します。

何かヒントありませんか?

宜しくお願いいたします。


(以下ソース)


UnitMain.pas

unit UnitMain;


interface


uses

 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

 Dialogs, StdCtrls, ExtCtrls,

 UnitPDFiumWrapper;


type

 TForm1 = class(TForm)

  Button1: TButton;

  procedure Button1Click(Sender: TObject);

 private

  { Private 宣言 }

 public

  { Public 宣言 }

  procedure RenderPDFToBitmap(const PDFFileName: string);

 end;


var

 Form1: TForm1;


implementation


{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);

var

 FileName : String;

begin

 FileName := 'Book1.pdf';


 RenderPDFToBitmap(FileName);

end;




procedure TForm1.RenderPDFToBitmap(const PDFFileName: string);

var

 PDFium: TPDFium;

 Document, Page: Pointer;

 PageCount, PageIdx: Integer;

 Bitmap: TBitmap;

 //

 DPI : Integer;

 PageW: Double;

 PageH: Double;

begin

 PDFium := TPDFium.Create;

 try

  Document := PDFium.LoadDocument(PDFFileName);

  if Document = nil then

   raise Exception.Create('Failed to load PDF document.');


  PageCount := PDFium.GetPageCount(Document);

outputdebugstring(PChar(Format('PDF 全%d頁', [PageCount])));

  for PageIdx := 0 to PageCount - 1 do

//  for PageIdx := 0 to 0 do

  begin

   Page := PDFium.LoadPage(Document, PageIdx);

   if Page = nil then

    raise Exception.CreateFmt('Failed to load page %d.', [PageIdx]);


PageW := PDFium.GetPageWidth(Page);

PageH := PDFium.GetPageHeight(Page);

outputdebugstring(PChar(Format('PDF W%f', [PageW])));

outputdebugstring(PChar(Format('PDF H%f', [PageH])));



   //

   DPI := 96;


   Bitmap := TBitmap.Create;

   try

    Bitmap.Width    := PDFium.PointToPixel(DPI, PageW);

    Bitmap.Height   := PDFium.PointToPixel(DPI, PageH);

    Bitmap.PixelFormat := pf16bit;

    PDFium.RenderPageToBitmap(Page, Bitmap); ←この中で

EAccessVioaltion


    // ビットマップを表示または保存する処理をここに追加

    Bitmap.SaveToFile(Format('Page_%d.bmp', [PageIdx]));

   finally

    Bitmap.Free;

    PDFium.ClosePage(Page);

   end;

  end;


  PDFium.CloseDocument(Document);

 finally

  PDFium.Free;

 end;

end;



end.




UnitPDFiumWrapper.pas

// PDFium.dllの入手先は以下のURLから

// https://github.com/bblanchon/pdfium-binaries

unit UnitPDFiumWrapper;


interface


uses

 Windows, SysUtils, Classes, Graphics;


type

 TPDFium = class

 private

  FPDFLibrary: HMODULE;


  // 使用する関数

  FPDF_LoadDocument   : function (file_path: PAnsiChar; password: PAnsiChar): Pointer; cdecl;

  FPDF_GetPageCount   : function (document: Pointer): Integer; cdecl;

  FPDF_LoadPage     : function (document: Pointer; page_index: Integer): Pointer; cdecl;

  FPDF_RenderPageBitmap : procedure (bitmap: HBITMAP; page: Pointer; start_x, start_y, size_x, size_y, rotate: Integer; flags: Integer); cdecl;

  FPDF_CloseDocument  : procedure (document: Pointer); cdecl;

  FPDF_ClosePage    : procedure (page: Pointer); cdecl;

  FPDF_InitLibrary   : procedure; cdecl;

  FPDF_DestroyLibrary  : procedure; cdecl;

  FPDF_GetPageWidth   : function (page: Pointer): double; cdecl;

  FPDF_GetPageHeight  : function (page: Pointer): double; cdecl;


  function LoadPDFium: Boolean;

  procedure UnloadPDFium;

 public

  constructor Create;

  destructor Destroy; override;


  function PointToPixel(const DPI: Integer; const Value: Extended): Integer;


  function LoadDocument(const FileName: string): Pointer;

  function GetPageCount(Document: Pointer): Integer;

  function LoadPage(Document: Pointer; const PageIdx: Integer): Pointer;

  procedure RenderPageToBitmap(Page: Pointer; Bitmap: TBitmap);

  procedure CloseDocument(Document: Pointer);

  procedure ClosePage(Page: Pointer);

  function GetPageWidth(Page: Pointer): Double;

  function GetPageHeight(Page: Pointer): Double;

 end;


implementation


const

 PDFIUM_DLL = 'pdfium.dll';


{ TPDFium }



// PointToPixel

function TPDFium.PointToPixel(const DPI: Integer; const Value: Extended): Integer;

begin

 Result := trunc(Value * DPI / 72);

end;



constructor TPDFium.Create;

begin

 inherited Create;

 if not LoadPDFium then

  raise Exception.Create('Failed to load PDFium library.');

 if Assigned(FPDF_InitLibrary) then

  FPDF_InitLibrary;

end;


destructor TPDFium.Destroy;

begin

 if Assigned(FPDF_DestroyLibrary) then

  FPDF_DestroyLibrary;

 UnloadPDFium;

 inherited Destroy;

end;


function TPDFium.LoadPDFium: Boolean;

begin

 FPDFLibrary := LoadLibrary(PDFIUM_DLL);

 if FPDFLibrary = 0 then

 begin

  raise Exception.CreateFmt('Failed to load PDFium DLL: %s', [SysErrorMessage(GetLastError)]);

 end;


 // 関数のアドレスを取得

 // FPDF_LoadDocument

 @FPDF_LoadDocument   := GetProcAddress(FPDFLibrary, 'FPDF_LoadDocument');

 if not Assigned(FPDF_LoadDocument) then raise Exception.Create('Failed to get address for FPDF_LoadDocument');

 // FPDF_GetPageCount

 @FPDF_GetPageCount   := GetProcAddress(FPDFLibrary, 'FPDF_GetPageCount');

 if not Assigned(FPDF_GetPageCount) then raise Exception.Create('Failed to get address for FPDF_GetPageCount');

 // FPDF_LoadPage

 @FPDF_LoadPage     := GetProcAddress(FPDFLibrary, 'FPDF_LoadPage');

 if not Assigned(FPDF_LoadPage) then raise Exception.Create('Failed to get address for FPDF_LoadPage');

 // FPDF_RenderPageBitmap

 @FPDF_RenderPageBitmap := GetProcAddress(FPDFLibrary, 'FPDF_RenderPageBitmap');

 if not Assigned(FPDF_RenderPageBitmap) then raise Exception.Create('Failed to get address for FPDF_RenderPageBitmap');

 // FPDF_CloseDocument

 @FPDF_CloseDocument  := GetProcAddress(FPDFLibrary, 'FPDF_CloseDocument');

 if not Assigned(FPDF_CloseDocument) then raise Exception.Create('Failed to get address for FPDF_CloseDocument');

 // FPDF_ClosePage

 @FPDF_ClosePage    := GetProcAddress(FPDFLibrary, 'FPDF_ClosePage');

 if not Assigned(FPDF_ClosePage) then raise Exception.Create('Failed to get address for FPDF_ClosePage');

 // FPDF_InitLibrary

 @FPDF_InitLibrary   := GetProcAddress(FPDFLibrary, 'FPDF_InitLibrary');

 if not Assigned(FPDF_InitLibrary) then raise Exception.Create('Failed to get address for FPDF_InitLibrary');

 // FPDF_DestroyLibrary

 @FPDF_DestroyLibrary  := GetProcAddress(FPDFLibrary, 'FPDF_DestroyLibrary');

 if not Assigned(FPDF_DestroyLibrary) then raise Exception.Create('Failed to get address for FPDF_DestroyLibrary');


 // FPDF_GetPageWidth

 @FPDF_GetPageWidth   := GetProcAddress(FPDFLibrary, 'FPDF_GetPageWidth');

 if not Assigned(FPDF_GetPageWidth) then raise Exception.Create('Failed to get address for FPDF_GetPageWidth');

 // FPDF_GetPageHeight

 @FPDF_GetPageHeight  := GetProcAddress(FPDFLibrary, 'FPDF_GetPageHeight');

 if not Assigned(FPDF_GetPageHeight) then raise Exception.Create('Failed to get address for FPDF_GetPageHeight');



 Result := True;

end;


procedure TPDFium.UnloadPDFium;

begin

 if FPDFLibrary <> 0 then

 begin

  FreeLibrary(FPDFLibrary);

  FPDFLibrary := 0;

 end;

end;


function AnsiToUtf8(const S: string): AnsiString;

begin

 Result := UTF8Encode(S);

end;


function TPDFium.LoadDocument(const FileName: string): Pointer;

begin

 if not Assigned(FPDF_LoadDocument) then

  raise Exception.Create('FPDF_LoadDocument is not assigned.');

 Result := FPDF_LoadDocument(PAnsiChar(AnsiToUtf8(FileName)), nil);

 if Result = nil then

  raise Exception.Create('Failed to load PDF document. File may be corrupted or incompatible.');

end;


function TPDFium.GetPageCount(Document: Pointer): Integer;

begin

 if not Assigned(FPDF_GetPageCount) then

  raise Exception.Create('FPDF_GetPageCount is not assigned.');

 Result := FPDF_GetPageCount(Document);

end;


function TPDFium.LoadPage(Document: Pointer; const PageIdx: Integer): Pointer;

begin

 if not Assigned(FPDF_LoadPage) then

  raise Exception.Create('FPDF_LoadPage is not assigned.');

 Result := FPDF_LoadPage(Document, PageIdx);

end;


procedure TPDFium.RenderPageToBitmap(Page: Pointer; Bitmap: TBitmap);

begin

 if not Assigned(FPDF_RenderPageBitmap) then

  raise Exception.Create('FPDF_RenderPageBitmap is not assigned.');


 // EAccessViolationが発生する

 FPDF_RenderPageBitmap(Bitmap.Canvas.Handle, Page, 0, 0, Bitmap.Width, Bitmap.Height, 0, 0);

end;


procedure TPDFium.CloseDocument(Document: Pointer);

begin

 if not Assigned(FPDF_CloseDocument) then

  raise Exception.Create('FPDF_CloseDocument is not assigned.');

 FPDF_CloseDocument(Document);

end;


procedure TPDFium.ClosePage(Page: Pointer);

begin

 if not Assigned(FPDF_ClosePage) then

  raise Exception.Create('FPDF_ClosePage is not assigned.');

 FPDF_ClosePage(Page);

end;


function TPDFium.GetPageWidth(Page: Pointer): Double;

begin

 if not Assigned(FPDF_GetPageWidth) then

  raise Exception.Create('FPDF_GetPageWidth is not assigned.');

 Result:= FPDF_GetPageWidth(Page);

end;


function TPDFium.GetPageHeight(Page: Pointer): Double;

begin

 if not Assigned(FPDF_GetPageHeight) then

  raise Exception.Create('FPDF_GetPageHeight is not assigned.');

 Result:= FPDF_GetPageHeight(Page);

end;


end.


kuro_m...@yahoo.co.jp

unread,
Dec 12, 2024, 6:51:38 PM12/12/24
to radstu...@googlegroups.com


お世話になります、黒川@Delphi7です。


自己レスです


 // EAccessViolationが発生する
 FPDF_RenderPageBitmap(Bitmap.Canvas.Handle, Page, 0, 0, Bitmap.Width, Bitmap.Height, 0, 0);


この部分で呼び出していたAPIですが、"FPDF_RenderPage"を使用する事でBitmapが取得できるようになりました。


失礼いたしました


----- Original Message -----

From: "kuro_ml_y2006 via Japan RAD Studio User Group" <radstu...@googlegroups.com>
To: "radstu...@googlegroups.com" <radstu...@googlegroups.com>
Date: 2024/12/11 水 17:47
Subject: [radstudio-jp:462] PDFiumを使ってみたいのですが
--
このメールは Google グループのグループ「Japan RAD Studio User Group」に登録しているユーザーに送られています。
このグループから退会し、グループからのメールの配信を停止するには radstudio-jp...@googlegroups.com にメールを送信してください。
このディスカッションを表示するには、https://groups.google.com/d/msgid/radstudio-jp/1635018801.9706.1733906855924%40mail.yahoo.co.jp にアクセスしてください。

mam

unread,
Dec 23, 2024, 9:06:20 PM12/23/24
to Japan RAD Studio User Group
黒川様
PDFiumを知りませんでしたが、これはとても素晴らしいですね。

Delphi7では使えないと思いますが、PDFiumLibライブラリを使うととても簡単に扱えますね。
https://github.com/ahausladen/PdfiumLib

私も使ってみました。
https://mam-mam.net/delphi/vcl_pdfium.html

情報ありがとうございます。



2024年12月13日金曜日 8:51:38 UTC+9 kuro_m...@yahoo.co.jp:
Reply all
Reply to author
Forward
0 new messages