Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с файлами PDF в проекте Delphi - пример, PDF2TIFF 
:(
    Опции темы
Prok12
  Дата 30.4.2018, 08:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 8.11.2011

Репутация: 3
Всего: 3



На одном из дружественных форумов наткнулся на программу-обёртку от Кроик Семёна для чтения из Delphi многостраничных документов в формате PDF.  smile  Построено на базе известной pdf.dll от Crome. Кое-что переделал-упростил в этой весьма полезной оболочке, так что получился самостоятельный pas-модуль для работы с pdf + небольшая демо-программка для сохранения прочитанного файла в Tiff, Jpeg или BMP. Текст этого вспомогательного модуля приведён ниже, хотя он есть и в составе проекта - по ссылке для скачивания.
Весь Delphi-проект прилагаю : PDF2TIFF  . Там необходимая DLL тоже внутри имеется.
Тестировал под Win10 64bit. Собирал в Tokyo 10.2.2, но указанная DLL нормально подключится только при компиляции под 32bit   smile .
 Надеюсь, кому-то будет полезно при работе с файлами *.pdf.  smile 
Код

// Delphi wrapper for Google Chrome's "pdf.dll"
// with GetPDFPageSizeByIndex
// Based on Simon Kroik, 06.2013-03.2018    >> Version 2.0  <<
// Tested with Delphi Tokyo 10.2.2, 32bit
unit MyChromePDFRender;

interface
uses Windows, Classes, Graphics, Types,  SysUtils, UITypes, Dialogs;

type TMyChromePDFRender = class(TPersistent)
// Private Declarations
   private
    FBuffer         : PChar;
    FBufferSize     : Int64;
    FPagesCount     : Integer;
    FMaxPageWidthCm : Single;
    FFullFileName   : string;
    LoadedDLL: Boolean;
    procedure RaiseIfPageNumberWrong(APageNumber: Integer);
    procedure Clear;
    function RenderPDFToDC(ADC: HDC;
     ARectLeft, ARectTop, ARectWidth, ARectHeight,
     APageNumber, ADpiX, ADpiY: Integer;
     ADoFitToBounds, ADoStretchToBounds,  ADoKeepAspectRatio,
     ADoCenterInBounds,  ADoAutoRotate: Boolean):  Boolean;
    function LoadPDFFromStream(AStream: TStream;
     ALength: Int64 =0 ): Boolean;
// Public Declarations
   public
    constructor Create;
    destructor Destroy; override;
    function LoadPDFFromFile(const APDFFile: TFileName): Boolean;
    function GetPageSizeInPixel(APageNumber, ADpiX, ADpiY: Integer;
     var AWidth, AHeight: Integer): Boolean;
    function RenderPDFToBitmap(
     ABitmap: Graphics.TBitmap;
     APageNumber, ADpiX, ADpiY: Integer;
     ADoAutoRotate, ADoCenterInBounds, ADoAutoSizeBitmap: Boolean):
     Boolean;
    property MaxPageWidthCm: Single read FMaxPageWidthCm;
    property FullFileName: string read FFullFileName;
    property PagesCount: Integer read FPagesCount;
    property SizeInBytes: int64 read FBufferSize;
   end;
//=====================================================================
implementation

const LibName  = 'pdf.dll';

var
   GetPDFDocInfo : procedure(
     pdf_buffer       : PChar;
     buffer_size      : Integer;
     page_count       : PInt;
     max_page_width   : PDouble);  cdecl;

   GetPDFPageSizeByIndex : function(
     pdf_buffer          : PChar;
     buffer_size         : Integer;
     page_number         : Integer;
     width               : PDouble;
     height              : PDouble): Boolean;  cdecl;

   RenderPDFPageToDC : function(
     pdf_buffer          : PChar;
     buffer_size         : Integer;
     page_number         : Integer;
     dc                  : HDC;
     dpi_x               : Integer;
     dpi_y               : Integer;
     bounds_origin_x     : Integer;
     bounds_origin_y     : Integer;
     bounds_width        : Integer;
     bounds_height       : Integer;
     fit_to_bounds       : Boolean;
     stretch_to_bounds   : Boolean;
     keep_aspect_ratio   : Boolean;
     center_in_bounds    : Boolean;
     autorotate          : Boolean): Boolean;  cdecl;

var internal_hLib: THandle;

///////////////////////////////////////////////////////////////////////
function InchToCm(AInch: Single): Single;
begin
Result := AInch * 2.54;
end;

//---------------------------------------------------------------------
procedure MyException(const ExceptMessage: String);
begin
MessageDlg(ExceptMessage, mtError, [mbAbort], 0);
raise EAbort.Create('');  // Silent
end;

//---------------------------------------------------------------------
procedure FreeLib;
begin
   If internal_hLib <> 0 then try
   FreeLibrary(internal_hLib);
   finally
   internal_hLib := 0;
   end;
end;

//---------------------------------------------------------------------
procedure LoadFun(var Fun: Pointer;  const FunName: WideString);
begin
Fun := nil;
Fun := GetProcAddress(internal_hLib, PWideChar(FunName));
If Fun = nil then MyException('Library "' + LibName +
 '" is not correct loaded.' + #13#10 + 'function "' +
 FunName + '" is not found.');
end;

//#####################################################################
{ TMyChromePDFRender }
//#####################################################################
constructor TMyChromePDFRender.Create;
var iLastErr: DWord;
begin
LoadedDLL := False;
   Try
   internal_hLib := LoadLibrary(LibName);
   iLastErr := GetLastError;
   If internal_hLib = 0 then MyException('Library "' + LibName +
    '" is not correct loaded.' + #13#10 + SysErrorMessage(iLastErr));
//.....................................................................
   LoadFun(@GetPDFDocInfo, 'GetPDFDocInfo');
   LoadFun(@GetPDFPageSizeByIndex, 'GetPDFPageSizeByIndex');
   LoadFun(@RenderPDFPageToDC, 'RenderPDFPageToDC');
   LoadedDLL := True;
   except
   FreeLib;
   end;
end;

//---------------------------------------------------------------------
procedure TMyChromePDFRender.Clear;
begin
inherited;
FreeMem(FBuffer);   FBuffer := nil;
FFullFileName := '';
FBufferSize := 0;
FPagesCount := 0;
FMaxPageWidthCm := 0;
end;

//---------------------------------------------------------------------
function TMyChromePDFRender.LoadPDFFromStream(AStream: TStream;
   ALength: Int64): Boolean;
var iPDFSize: Int64;   fMaxPageWidthPix72dpi: Double;
begin
Result := False;
   If LoadedDLL then try
      If ALength > 0 then begin
      iPDFSize := ALength;
      If AStream.Position + iPDFSize > AStream.Size then
       MyException('Length-Parameter is over the stream size');
      end
      else iPDFSize := AStream.Size - AStream.Position;
   If iPDFSize > High(Int64) then
    MyException('PDF is too big: ' +
    IntToStr(iPDFSize div (1024*1024)) + ' MB');
   Clear;
   FBufferSize := iPDFSize;
//............................................
   GetMem(FBuffer, FBufferSize);
   AStream.ReadBuffer(FBuffer^, FBufferSize);
//............................................
   GetPDFDocInfo(
     FBuffer,
     FBufferSize,
     @FPagesCount,
     @fMaxPageWidthPix72dpi);
   FMaxPageWidthCm := InchToCm(fMaxPageWidthPix72dpi / 72.0);
   Result := True;
   except
   Clear;
   end;
end;

//---------------------------------------------------------------------
function TMyChromePDFRender.GetPageSizeInPixel(APageNumber,
  ADpiX, ADpiY: Integer; var AWidth, AHeight: Integer): Boolean;
var fWidthPix72dpi , fHeightPix72dpi : Double;
begin
Result := False;
   If LoadedDLL then try
   RaiseIfPageNumberWrong(APageNumber);
   Result := GetPDFPageSizeByIndex(
      FBuffer,           // pdf_buffer
      FBufferSize,       // buffer_size
      APageNumber - 1,   // page_number
      @fWidthPix72dpi,   // width
      @fHeightPix72dpi); // height
   AWidth := Round(fWidthPix72dpi / 72.0 * ADpiX);
   AHeight := Round(fHeightPix72dpi  / 72.0 * ADpiY);
   finally
   end;
end;

//---------------------------------------------------------------------
function TMyChromePDFRender.RenderPDFToDC(ADC: HDC;
  ARectLeft, ARectTop, ARectWidth, ARectHeight,
  APageNumber, ADpiX, ADpiY: Integer;
  ADoFitToBounds, ADoStretchToBounds,  ADoKeepAspectRatio,
  ADoCenterInBounds,  ADoAutoRotate: Boolean): Boolean;
begin
Result := False;
   If LoadedDLL then try
   RaiseIfPageNumberWrong(APageNumber);
// From: https://chromium.googlesource.com/chromium/src/+/master/pdf/pdf.h
//
// |pdf_buffer| is the buffer that contains the entire PDF document to be
//     rendered.
// |buffer_size| is the size of |pdf_buffer| in bytes.
// |page_number| is the 0-based index of the page to be rendered.
// |dc| is the device context to render into.
// |dpi_x| and |dpi_y| are the x and y resolutions respectively. If either
//     value is -1, the dpi from the DC will be used.
// |bounds_origin_x|, |bounds_origin_y|, |bounds_width| and |bounds_height|
//     specify a bounds rectangle within the DC in which to render the PDF
//     page.
// |fit_to_bounds| specifies whether the output should be shrunk to fit the
//     supplied bounds if the page size is larger than the bounds in any
//     dimension. If this is false, parts of the PDF page that lie outside
//     the bounds will be clipped.
// |stretch_to_bounds| specifies whether the output should be stretched to fit
//     the supplied bounds if the page size is smaller than the bounds in any
//     dimension.
// If both |fit_to_bounds| and |stretch_to_bounds| are true, then
//     |fit_to_bounds| is honored first.
// |keep_aspect_ratio| If any scaling is to be done is true, this flag
//     specifies whether the original aspect ratio of the page should be
//     preserved while scaling.
// |center_in_bounds| specifies whether the final image (after any scaling is
//     done) should be centered within the given bounds.
// |autorotate| specifies whether the final image should be rotated to match
//     the output bound.
// Returns false if the document or the page number are not valid.
   Result := RenderPDFPageToDC(
      FBuffer,               // pdf_buffer
      FBufferSize,           // buffer_size
      APageNumber - 1,       // page_number
      ADC,                   // dc
      ADpiX,                 // dpi_x
      ADpiY,                 // dpi_y
      ARectLeft,             // bounds_origin_x
      ARectTop,              // bounds_origin_y
      ARectWidth,            // bounds_width
      ARectHeight,           // bounds_height
      ADoFitToBounds,        // fit_to_bounds
      ADoStretchToBounds,    // stretch_to_bounds
      ADoKeepAspectRatio,    // keep_aspect_ratio
      ADoCenterInBounds,     // center_in_bounds
      ADoAutoRotate);        // autorotate
   finally
   end;
end;

//---------------------------------------------------------------------
function TMyChromePDFRender.RenderPDFToBitmap(
  ABitmap: Graphics.TBitmap;
  APageNumber, ADpiX, ADpiY: Integer;
  ADoAutoRotate, ADoCenterInBounds, ADoAutoSizeBitmap: Boolean):
  Boolean;
var iW, iH: Integer;
begin
Result := False;
If not LoadedDLL then Exit;  // Если функции из DLL не были загружены
   If ADoAutoSizeBitmap then begin
   If not GetPageSizeInPixel(APageNumber, ADpiX, ADpiY, iW, iH)
    then Exit;
   ABitmap.Width := iW;    ABitmap.Height := iH;
   end;
//.....................................................................
ABitmap.Canvas.Brush.Style := bsSolid;
ABitmap.Canvas.Brush.Color := clWhite;
ABitmap.Canvas.FillRect(Rect(0,0,iW, iH));
//.....................................................................
Result := RenderPDFToDC(
  ABitmap.Canvas.Handle,    // ADC
  0,                        // ARectLeft
  0,                        // ARectTop
  ABitmap.Width,            // ARectWidth
  ABitmap.Height,           // ARectHeight
  APageNumber,              // APageNumber
  ADpiX,                    // ADpiX
  ADpiY,                    // ADpiY
  not ADoAutoSizeBitmap,    // ADoFitToBounds
  false,                    // ADoStretchToBounds
  true,                     // ADoKeepAspectRatio
  ADoCenterInBounds,        // ADoCenterInBounds
  ADoAutoRotate );          // ADoAutoRotate
end;

//---------------------------------------------------------------------
function TMyChromePDFRender.LoadPDFFromFile(
  const APDFFile: TFileName): Boolean;
var FStr: TFileStream;
begin
   If LoadedDLL and (Trim(APDFFile) <> '') then
   begin
   FStr := TFileStream.Create(APDFFile, fmOpenRead or fmShareDenyNone);
   Result := LoadPDFFromStream(FStr);
   If Result then FFullFileName := APDFFile;
   FreeAndNil(FStr);
   end
   else Result := False;
end;

//---------------------------------------------------------------------
procedure TMyChromePDFRender.RaiseIfPageNumberWrong(
 APageNumber: Integer);
begin
If FPagesCount < 1 then
 MyException('There are 0 pageses in document')
 else if (APageNumber < 1) or (APageNumber > FPagesCount) then
 MyException('Page-Number "' + IntToStr(APageNumber) +
 '" is out of range [1..' + IntToStr(FPagesCount) + ']');
end;

//---------------------------------------------------------------------
destructor TMyChromePDFRender.Destroy;
begin
Clear;
FreeLib;
inherited;
end;

end.


Это сообщение отредактировал(а) Prok12 - 30.4.2018, 08:52
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1221 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.