Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Открыть PDF из MemoryStream / 25 сообщений из 104, страница 1 из 5
22.12.2016, 08:44
    #39372546
MaratIsk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Есть ли умеющий это просмотровщик ?
...
Рейтинг: 0 / 0
22.12.2016, 08:57
    #39372548
Евгений, Екатеринбург
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
MaratIsk,
Есть, но чуть платный
www.gnostice.com
...
Рейтинг: 0 / 0
22.12.2016, 09:53
    #39372579
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Наш тоже умеет
...
Рейтинг: 0 / 0
22.12.2016, 11:32
    #39372676
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
white_niggerНаш тоже умеет

вот только формат 1.6 не понимает, а так-то да
...
Рейтинг: 0 / 0
22.12.2016, 12:01
    #39372719
Евгений, Екатеринбург
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
defecator_,
PDF TollKit тоже не безгрешен - позволяет наносить дополнительные текстовые и графические метки, но текст меток не поддерживает юникод.
авторCurrently PDFToolkit supports only the following encoding. If the russian font is encoded as Unicode, it is currently not supported by PDFToolkit.
...
We have plans to support unicode encoding and it will be implemented in one of the future release. We will notify you as soon as we support Unicode in PDFToolkit.
Хотя на сайте говорится о поддержке юникода.
Но это было пару лет назад, может с тех пор что и изменилось.
...
Рейтинг: 0 / 0
22.12.2016, 12:10
    #39372736
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
defecator_вот только формат 1.6 не понимает, а так-то да И много видел документов в этом формате?
...
Рейтинг: 0 / 0
22.12.2016, 12:21
    #39372748
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
white_niggerdefecator_вот только формат 1.6 не понимает, а так-то да И много видел документов в этом формате?

у меня таких документов море разливанное.
Кроме родного Adobe Reader и компонентов от Gnostice никто не умеет 1.6 открывать.
...
Рейтинг: 0 / 0
22.12.2016, 13:19
    #39372850
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
defecator_у меня таких документов море разливанное.
Кроме родного Adobe Reader и компонентов от Gnostice никто не умеет 1.6 открывать.В 1.6 добавилось внедренное мультимедиа, 3D, XML-формы, AES-шифрование. Ни разу не встречал такой PDF :) Можешь кинуть какой-нить для примера?
...
Рейтинг: 0 / 0
22.12.2016, 13:24
    #39372862
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
white_niggerdefecator_у меня таких документов море разливанное.
Кроме родного Adobe Reader и компонентов от Gnostice никто не умеет 1.6 открывать.В 1.6 добавилось внедренное мультимедиа, 3D, XML-формы, AES-шифрование. Ни разу не встречал такой PDF :) Можешь кинуть какой-нить для примера?

Вот, самый простой в формате 1.6:
http://rgho.st/8PrgW27Gw
...
Рейтинг: 0 / 0
22.12.2016, 13:28
    #39372876
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
pdfium.dll
бесплатный
есть дельфовая обертка
...
Рейтинг: 0 / 0
22.12.2016, 13:38
    #39372896
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
defecator_Вот, самый простой в формате 1.6:
http://rgho.st/8PrgW27Gw Нормально он открывается у нас. Единственно мы аннотации пока не поддерживаем, суг есть на это.
...
Рейтинг: 0 / 0
22.12.2016, 13:46
    #39372908
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
white_niggerdefecator_Вот, самый простой в формате 1.6:
http://rgho.st/8PrgW27Gw Нормально он открывается у нас. Единственно мы аннотации пока не поддерживаем, суг есть на это.
это простой, без XML и медиа, но у меня на DevExp 16.1 не открывается, просто белое поле без ничего.
при этом 1.5 версия открывается
...
Рейтинг: 0 / 0
22.12.2016, 14:20
    #39372974
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
defecator_без XML и медиаДа это не поддерживается, но повторюсь, наверно 99% имеющихся PDF не содержат в себе ни 3Д, ни медиа, ни XML-форм. Большинству эти новомодности нужны. Кстати шифрование поддерживается. Плюс, как написал разработчик "по сравнению 16.1 в 16.2 были серьезные изменения в плане рендеринга" - правда я не в курсе, что скрывается за этой фразой :) Продукт новый и активно развивается.
...
Рейтинг: 0 / 0
22.12.2016, 14:23
    #39372977
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
white_niggerdefecator_без XML и медиаДа это не поддерживается, но повторюсь, наверно 99% имеющихся PDF не содержат в себе ни 3Д, ни медиа, ни XML-форм. Большинству эти новомодности нужны. Кстати шифрование поддерживается. Плюс, как написал разработчик "по сравнению 16.1 в 16.2 были серьезные изменения в плане рендеринга" - правда я не в курсе, что скрывается за этой фразой :) Продукт новый и активно развивается.

ну, посмотрим.
Я пока пользуюсь Gnostice, ничего лучшего и мощного из нативного для Delphi (пока ещё ?) нет.
...
Рейтинг: 0 / 0
22.12.2016, 14:29
    #39372985
Гаджимурадов Рустам
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Дефекатор,

А зачем эта игра в догонялки, если есть
бесплатный вьювер от производителя?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.12.2016, 14:49
    #39373002
Товарищ младший сержант
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Квейдpdfium.dll
бесплатный
есть дельфовая обертка
Класс, спасибо.
...
Рейтинг: 0 / 0
22.12.2016, 14:55
    #39373007
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Товарищ младший сержантКвейдpdfium.dll
бесплатный
есть дельфовая обертка
Класс, спасибо.

Обертка от Andreas Hausladen

https://github.com/ahausladen/PdfiumLib

У меня в проекте взлетело
...
Рейтинг: 0 / 0
22.12.2016, 15:46
    #39373068
makhaon
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Гаджимурадов Рустам,

Лишние зависимости. Мы тоже используем гностис.
...
Рейтинг: 0 / 0
22.12.2016, 16:15
    #39373101
defecator_
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Гаджимурадов РустамДефекатор,

А зачем эта игра в догонялки, если есть
бесплатный вьювер от производителя?


вьювер в свою программу не встроишь, да много зависимостей получается.
и нельзя через него оперировать страницами, как угодно - вытащить текст, добавить что-то, удалить страницу и т.д.
...
Рейтинг: 0 / 0
22.12.2016, 16:35
    #39373126
MaratIsk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
господа-товарищи,
речь не о бесплатных вьюерах
а о возможности просматривать мемористрем
без необходимости сохранять предварительно в файл
...
Рейтинг: 0 / 0
22.12.2016, 16:49
    #39373136
Товарищ младший сержант
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
MaratIsk,

а в чем проблема? Что-то из предложенного заставляет предварительно в файл сохранять?
...
Рейтинг: 0 / 0
22.12.2016, 16:53
    #39373144
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
MaratIskгоспода-товарищи,
речь не о бесплатных вьюерах
а о возможности просматривать мемористрем
без необходимости сохранять предварительно в файл

pdfium.dll

функция LoadMemDocument

для просмотра нужной страницы вызываешь RenderPage с параметрами, работает с Canvas

я эту библиотеку юзаю в своем приложении, косяков нет
...
Рейтинг: 0 / 0
22.12.2016, 17:09
    #39373162
MaratIsk
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Квейд,

буду признателен за пример кода
...
Рейтинг: 0 / 0
22.12.2016, 17:30
    #39373187
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
MaratIskКвейд,

буду признателен за пример кода

Я обернул вьювер в наследник от TGraphicControl (T24NSPDFViewer = class(TGraphicControl))
Подключаешь его к форме, инициализируешь контрол, вызываешь LoadFromXXX, страницы крутятся через вызов ScrollBy.
Модуль используется в реальном проекте. Код мой, делайте что угодно.

Необходимо наличие вышеуказанной DLL, она есть в свободном доступе.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
unit vcl24NSPDFViewer;

interface

uses
  System.SysUtils, System.Variants,
  System.Classes, System.Types,
  System.SyncObjs,
  Winapi.Windows, Winapi.Messages,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms,
  Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls,
  Generics.Collections,

  IdComponent, IdHTTP;

const
  WM_DONETHREAD = WM_USER + 1;
  WM_RENDERBITMAP = WM_USER + 2;
  WM_RELEASEBITMAP = WM_USER + 3;
  WM_DOWNLOADFILE = WM_USER + 4;

type
  TPDFPointer = record end;
  TPDFDocument = ^TPDFPointer;
  TPDFPage = ^TPDFPointer;

const
  PDF_LIBRARY_NAME = 'PDFIUM.DLL';

type
  TPDFClosePage = procedure(APage: Pointer); stdcall;
  TPDFInitLibrary = procedure; stdcall;
  TPDFDestroyLibrary = procedure; stdcall;
  TPDFGetPageCount = function(ADocument: Pointer): Integer; stdcall;
  TPDFCloseDocument = procedure(ADocument: Pointer); stdcall;
  TPDFLoadMemDocument = function(ABuffer: Pointer; ASize: Integer;
    APassword: PAnsiChar): Pointer; stdcall;
  TPDFGetPageSizeByIndex = function(ADocument: Pointer; APage: Integer;
    var AWidth, AHeight: Double): Integer; stdcall;
  TPDFGetPageWidth = function(APage: Pointer): Double; stdcall;
  TPDFGetPageHeight = function(APage: Pointer): Double; stdcall;
  TPDFRenderPage = procedure(ADC: HDC; APage: Pointer;
    ALeft, ATop, AWidth, AHeight, ARotate, AFlags: Integer); stdcall;
  TPDFLoadPage = function(ADocument: Pointer; APage: Integer): TPDFPage; stdcall;

  T24NSDocumentPage = class;
  T24NSPDFViewer = class;


  T24NSDownloader = class(TIdHTTP);

  T24NSHelperThread = class(TThread)
  private
    FViewer: T24NSPDFViewer;
    FMessageLoop: Boolean;
  protected
    procedure Execute; override;
    procedure Invalidate;
    procedure RenderBitmap(const AMsg: TMsg);
    procedure ReleaseBitmap(const AMsg: TMsg);
  public
    constructor Create(AViewer: T24NSPDFViewer);
    procedure Done;
    procedure WaitLooping;
  end;

  TPDFLibrary = packed record
  public
    ClosePage: TPDFClosePage;
    InitLibrary: TPDFInitLibrary;
    RenderPage: TPDFRenderPage;
    LoadPage: TPDFLoadPage;
    DestroyLibrary: TPDFDestroyLibrary;
    GetPageSizeByIndex: TPDFGetPageSizeByIndex;
    GetPageCount: TPDFGetPageCount;
    CloseDocument: TPDFCloseDocument;
    GetPageWidth: TPDFGetPageWidth;
    GetPageHeight: TPDFGetPageHeight;
    LoadMemDocument: TPDFLoadMemDocument;
  end;

  T24NSDocumentEngine = class(TObject)
  strict private
    FPDFLibrary: TPDFLibrary;
    FDocument: TPDFDocument;
    FMemoryBuffer: TMemoryStream;
    FModule: HMODULE;
    procedure FreeDocument;
  public
    constructor Create;
    destructor Destroy; override;
    procedure LoadFromStream(AStream: TStream);
    function Initialized: Boolean; inline;
    function PageCount: Integer; inline;
    property PDFLibrary: TPDFLibrary read FPDFLibrary;
    property Document: TPDFDocument read FDocument;
  end;

  T24NSDocumentPage = class(TObject)
  strict private
    FEngine: T24NSDocumentEngine;
    FBitmap: TBitmap;
    FIndex: Integer;
    FWidth: Double;
    FHeight: Double;
    FBitmapRendered: Boolean;
    FTimer: TTimer;
    FViewer: T24NSPDFViewer;
    FBlendValue: Integer;
    procedure TimerTick(Sender: TObject);
    procedure UpdatePage;
  public
    constructor Create(AViewer: T24NSPDFViewer; AIndex: Integer);
    destructor Destroy; override;
    function RenderedHeight(AWidth: Integer): Integer;
    procedure ReleaseBitmap;
    procedure RenderBitmap(AWidth: Integer);
    procedure ResetTimer; inline;
    procedure PrereleaseBitmap; inline;
    property BlendValue: Integer read FBlendValue;
    property Timer: TTimer read FTimer;
    property BitmapRendered: Boolean read FBitmapRendered;
    property Width: Double read FWidth;
    property Height: Double read FHeight;
    property Bitmap: TBitmap read FBitmap;
  end;

  T24NSDocumentPages = class(TObject)
  strict private
    FPages: TObjectList<T24NSDocumentPage>;
    FEngine: T24NSDocumentEngine;
    FPagesHeight: Integer;
    FViewer: T24NSPDFViewer;
  protected
    function GetCount: Integer; inline;
    procedure PreparePages;
  public
    constructor Create(AViewer: T24NSPDFViewer);
    destructor Destroy; override;
    function Page(AIndex: Integer): T24NSDocumentPage; inline;
    function First: T24NSDocumentPage; inline;
    function Last: T24NSDocumentPage; inline;
    property Count: Integer read GetCount;
    property PagesHeight: Integer read FPagesHeight;
  end;

  T24NSPDFViewer = class(TGraphicControl)
  strict private
    FEngine: T24NSDocumentEngine;
    FPages: T24NSDocumentPages;
    FDownloader: T24NSDownloader;
    FHelperThread: T24NSHelperThread;
    FViewOffset: Integer;
    FBlendFunction: TBlendFunction;
    FOnReady: TNotifyEvent;
    FDocumentLoaded: Boolean;
    FDocumentLoading: Boolean;
    FDocumentProgress: Integer;
    FBeginDocument: Boolean;
    FEndDocument: Boolean;
    FPainting: Boolean;
  protected
    procedure ReleaseBitmap(APageIndex: Integer; ABitmap: TBitmap); inline;
    procedure RenderBitmap(APageIndex: Integer; ABitmap: TBitmap); inline;
    procedure DownloadWork(Sender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
    procedure Paint; override;
    property Engine: T24NSDocumentEngine read FEngine;
    property Pages: T24NSDocumentPages read FPages;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure AfterConstruction; override;
    procedure ScrollBy(ADelta: Integer);
    procedure Ready;
    procedure LoadFromFile(const AFileName: string);
    procedure LoadFromURL(const AURL: string);
    procedure LoadFromStream(AStream: TStream);
    property OnReady: TNotifyEvent read FOnReady write FOnReady;
    property Painting: Boolean read FPainting;
    property EndDocument: Boolean read FEndDocument;
    property BeginDocument: Boolean read FBeginDocument;
  end;

implementation

resourcestring
  RST_PDFIUMNOTLOADED = 'PDFIUM.DLL IS NOT LOADED CORRECTLY';


const
  DEF_FONT_SIZE = 38;
  DEF_FONT_NAME = 'Impact';
  DEF_FONT_COLOR = $DADADA;
  DEF_BLENDING_STEP = 32;
  DEF_BLENDING_INTERVAL = 32;

{ T24NSDocumentEngine }

constructor T24NSDocumentEngine.Create;
begin
  inherited Create;
  FMemoryBuffer := nil;
  FModule := SafeLoadLibrary(PDF_LIBRARY_NAME);
  with FPDFLibrary do
  begin
    if FModule = 0 then
      raise Exception.CreateRes(@RST_PDFIUMNOTLOADED);
    InitLibrary := GetProcAddress(FModule, '_FPDF_InitLibrary@0');
    DestroyLibrary := GetProcAddress(FModule, '_FPDF_DestroyLibrary@0');
    RenderPage := GetProcAddress(FModule, '_FPDF_RenderPage@32');
    LoadPage := GetProcAddress(FModule, '_FPDF_LoadPage@8');
    GetPageWidth := GetProcAddress(FModule, '_FPDF_GetPageWidth@4');
    GetPageHeight := GetProcAddress(FModule, '_FPDF_GetPageHeight@4');
    GetPageCount := GetProcAddress(FModule, '_FPDF_GetPageCount@4');
    LoadMemDocument := GetProcAddress(FModule, '_FPDF_LoadMemDocument@12');
    CloseDocument := GetProcAddress(FModule, '_FPDF_CloseDocument@4');
    ClosePage := GetProcAddress(FModule, '_FPDF_ClosePage@4');
    GetPageSizeByIndex := GetProcAddress(FModule, '_FPDF_GetPageSizeByIndex@16');
    InitLibrary
  end
end;

destructor T24NSDocumentEngine.Destroy;
begin
  if Initialized then
  begin
    FreeDocument;
    FreeAndNil(FMemoryBuffer);
    FPDFLibrary.DestroyLibrary;
    FreeLibrary(FModule)
  end;
  inherited Destroy
end;

procedure T24NSDocumentEngine.FreeDocument;
begin
  if FDocument <> nil then
    FPDFLibrary.CloseDocument(FDocument);
  FDocument := nil;
  FreeAndNil(FMemoryBuffer);
  FMemoryBuffer := TMemoryStream.Create
end;

function T24NSDocumentEngine.Initialized: Boolean;
begin
  Result := FModule <> 0
end;

procedure T24NSDocumentEngine.LoadFromStream(AStream: TStream);
begin
  if Initialized then
  begin
    FreeDocument;
    if AStream.Size > 0 then
      try
        FMemoryBuffer.LoadFromStream(AStream);
        with FMemoryBuffer, FPDFLibrary do
          FDocument := LoadMemDocument(Memory, Size, nil)
      except
        FreeDocument
      end
  end
end;

function T24NSDocumentEngine.PageCount: Integer;
begin
  Result := 0;
  if Initialized and (FDocument <> nil) then
    Result := FPDFLibrary.GetPageCount(FDocument)
end;

{ T24NSPDFViewer }

procedure T24NSPDFViewer.AfterConstruction;
begin
  inherited AfterConstruction;
  FHelperThread.WaitLooping
end;

constructor T24NSPDFViewer.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FViewOffset := 0;
  FBeginDocument := False;
  FEndDocument := False;
  FDocumentLoaded := False;
  FDocumentLoading := False;
  FPainting := False;
  FDocumentProgress := 0;
  FBlendFunction.BlendOp := AC_SRC_OVER;
  FBlendFunction.BlendFlags := 0;
  FBlendFunction.SourceConstantAlpha := 255;
  FBlendFunction.AlphaFormat := 0;
  Color := clWhite;
  FEngine := T24NSDocumentEngine.Create;
  FPages := T24NSDocumentPages.Create(Self);
  FHelperThread := T24NSHelperThread.Create(Self);

  FDownloader := T24NSDownloader.Create(Self);
  FDownloader.AllowCookies := True;
  FDownloader.HandleRedirects := True
end;

destructor T24NSPDFViewer.Destroy;
begin
  FHelperThread.Done;
  FreeAndNil(FHelperThread);
  FreeAndNil(FPages);
  FreeAndNil(FEngine);
  inherited Destroy
end;


procedure T24NSPDFViewer.DownloadWork(Sender: TObject; AWorkMode: TWorkMode; AWorkCount: Int64);
var
  ContentLength: Int64;
begin
  ContentLength := FDownloader.Response.ContentLength;
  FDocumentProgress := 100 * AWorkCount div ContentLength;
  TWinControl(Owner).Repaint
end;

procedure T24NSPDFViewer.LoadFromFile(const AFileName: string);
var
  Stream: TStream;
begin
  Stream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite);
  try
    LoadFromStream(Stream)
  finally
    FreeAndNil(Stream)
  end
end;

procedure T24NSPDFViewer.LoadFromStream(AStream: TStream);
begin
  try
    if AStream.Size = 0 then
      Abort;
    AStream.Position := 0;
    FEngine.LoadFromStream(AStream);
    FPages.PreparePages;
    Ready;
    Repaint
  except
    FDocumentLoaded := False
  end
end;


procedure T24NSPDFViewer.LoadFromURL(const AURL: string);
var
  Stream: TStream;
begin
  Stream := TMemoryStream.Create;
  FDocumentLoading := True;
  try
    FDownloader.OnWork := DownloadWork;
    FDocumentLoaded := False;
    TWinControl(Owner).Repaint;
    try
      FDownloader.Get(AURL, Stream);
      FDocumentLoading := False;
      LoadFromStream(Stream)
    except
      Ready
    end
  finally
    FDownloader.OnWork := nil;
    FDocumentProgress := 0;
    FreeAndNil(Stream)
  end
end;

procedure T24NSPDFViewer.Paint;
var
  X, Y: Integer;
  R: TRect;
  RealHeight: Integer;
  I: Integer;
  Progress: string;
  Size: TSize;
begin
  FPainting := True;
  try
    with Canvas do
    begin
      Brush.Style := bsSolid;
      Brush.Color := Color;
      FillRect(ClientRect)
    end;
    if FDocumentLoading then
    begin
      Progress := Concat(FDocumentProgress.ToString, '%');
      with Canvas.Font do
      begin
        Name := DEF_FONT_NAME;
        Size := DEF_FONT_SIZE;
        Color := DEF_FONT_COLOR
      end;
      Size := Canvas.TextExtent(Progress);
      X := (ClientWidth - Size.Width) div 2;
      Y := (ClientHeight - Size.Height) div 2;
      Canvas.TextOut(X, Y, Progress)
    end;
    if FDocumentLoaded then
    begin
      X := 0;
      Y := 0;
      Dec(Y, FViewOffset);
      for I := 0 to Pred(FPages.Count) do
      begin
        RealHeight := FPages.Page(I).RenderedHeight(ClientWidth);
        if ((Y + RealHeight) > 0) and (Y < ClientHeight) then
        begin
          if not FPages.Page(I).BitmapRendered then
            RenderBitmap(I, nil)
          else
          begin
            R := Rect(X, Y, ClientWidth, Y + RealHeight);
            if FPages.Page(I).Timer.Enabled then
            begin
              FBlendFunction.SourceConstantAlpha := FPages.Page(I).BlendValue;
              AlphaBlend(Canvas.Handle, X, Y, ClientWidth, RealHeight,
                FPages.Page(I).Bitmap.Canvas.Handle,
                0, 0, ClientWidth, RealHeight, FBlendFunction)
            end
            else
              BitBlt(Canvas.Handle, X, Y, ClientWidth, RealHeight,
                FPages.Page(I).Bitmap.Canvas.Handle, 0, 0, SRCCOPY)
          end
        end
        else
        begin
          if FPages.Page(I).BitmapRendered then
          begin
            FPages.Page(I).PrereleaseBitmap;
            ReleaseBitmap(I, FPages.Page(I).Bitmap)
          end;
        end;
        Inc(Y, RealHeight)
      end;
{$IFDEF 24NSDEBUG}
      Canvas.TextOut(0, 0, FViewOffset.ToString)
{$ENDIF}
    end
  finally
    FPainting := False
  end
end;

procedure T24NSPDFViewer.Ready;
begin
  FDocumentLoading := False;
  FDocumentLoaded := True;
  FBeginDocument := True;
  FEndDocument := False;
  FViewOffset := 0;
  if Assigned(FOnReady) then
    FOnReady(Self);
  Invalidate
end;

procedure T24NSPDFViewer.ReleaseBitmap(APageIndex: Integer; ABitmap: TBitmap);
begin
  PostThreadMessage(FHelperThread.ThreadID, WM_RELEASEBITMAP, WPARAM(APageIndex), LPARAM(ABitmap))
end;

procedure T24NSPDFViewer.RenderBitmap(APageIndex: Integer; ABitmap: TBitmap);
begin
  PostThreadMessage(FHelperThread.ThreadID, WM_RENDERBITMAP, WPARAM(APageIndex), LPARAM(ClientWidth))
end;

procedure T24NSPDFViewer.ScrollBy(ADelta: Integer);
var
  Y: Integer;
begin
  FBeginDocument := False;
  FEndDocument := False;
  if FDocumentLoaded then
  begin
    Inc(FViewOffset, ADelta);
    if FViewOffset <= 0 then
      FViewOffset := 0;
    Y := Pages.PagesHeight - ClientHeight;
    if Y < 0 then
      Y := 0;
    if FViewOffset > Y then
      FViewOffset := Y;
    FBeginDocument := FViewOffset = 0;
    FEndDocument := FViewOffset = Y;
    Invalidate
  end
end;

{ T24NSDocumentPages }

constructor T24NSDocumentPages.Create(AViewer: T24NSPDFViewer);
begin
  inherited Create;
  FViewer := AViewer;
  FEngine := AViewer.Engine;
  FPagesHeight := 0;
  FPages := TObjectList<T24NSDocumentPage>.Create(True)
end;

destructor T24NSDocumentPages.Destroy;
begin
  FreeAndNil(FPages);
  inherited Destroy
end;

function T24NSDocumentPages.GetCount: Integer;
begin
  Result := FPages.Count
end;

function T24NSDocumentPages.First: T24NSDocumentPage;
begin
  if Count = 0 then
    Exit(nil);
  Exit(Page(0))
end;

function T24NSDocumentPages.Last: T24NSDocumentPage;
begin
  if Count = 0 then
    Exit(nil);
  Exit(Page(Pred(Count)))
end;

procedure T24NSDocumentPages.PreparePages;
var
  Page: T24NSDocumentPage;
  I: Integer;
  X: Integer;
begin
  FPagesHeight := 0;
  FPages.Clear;
  X := FViewer.ClientWidth;
  for I := 0 to Pred(FEngine.PageCount) do
  begin
    Page := T24NSDocumentPage.Create(FViewer, I);
    FPages.Add(Page);
    FPagesHeight := FPagesHeight + Page.RenderedHeight(X)
  end
end;

function T24NSDocumentPages.Page(AIndex: Integer): T24NSDocumentPage;
begin
  Result := FPages.List[AIndex]
end;

{ T24NSDocumentPage }

constructor T24NSDocumentPage.Create(AViewer: T24NSPDFViewer; AIndex: Integer);
begin
  inherited Create;
  FBitmap := nil;
  FViewer := AViewer;
  FIndex := AIndex;
  FBitmapRendered := False;
  FBlendValue := 0;
  FEngine := AViewer.Engine;
  FTimer := TTimer.Create(nil);
  FTimer.OnTimer := TimerTick;
  FTimer.Enabled := False;
  FTimer.Interval := DEF_BLENDING_INTERVAL;
  UpdatePage;
  ReleaseBitmap
end;

destructor T24NSDocumentPage.Destroy;
begin
  FreeAndNil(FTimer);
  FreeAndNil(FBitmap);
  inherited Destroy
end;

procedure T24NSDocumentPage.PrereleaseBitmap;
begin
  ResetTimer;
  FBitmapRendered := False
end;

procedure T24NSDocumentPage.UpdatePage;
begin
  with FEngine, FEngine.PDFLibrary do
    GetPageSizeByIndex(Document, FIndex, FWidth, FHeight)
end;

procedure T24NSDocumentPage.ReleaseBitmap;
begin
  FBitmapRendered := False;
  FreeAndNil(FBitmap);
  FBitmap := TBitmap.Create
end;

procedure T24NSDocumentPage.RenderBitmap(AWidth: Integer);
var
  DisplayWidth: Integer;
  DisplayHeight: Integer;
  Page: TPDFPage;
begin
  if not FBitmapRendered then
  begin
    Page := FEngine.PDFLibrary.LoadPage(FEngine.Document, FIndex);
    try
      FBitmap.Canvas.Lock;
      try
        DisplayWidth := AWidth;
        DisplayHeight := RenderedHeight(DisplayWidth);
        FBitmap.SetSize(DisplayWidth, DisplayHeight);
        FEngine.PDFLibrary.RenderPage(FBitmap.Canvas.Handle,
          Page, 0, 0, DisplayWidth, DisplayHeight, 0, 0)
      finally
        FBitmap.Canvas.Unlock
      end;
      FBlendValue := 0;
      FBitmapRendered := True;
      Timer.Enabled := True
    finally
      FEngine.PDFLibrary.ClosePage(Page)
    end
  end
end;

function T24NSDocumentPage.RenderedHeight(AWidth: Integer): Integer;
begin
  Result := Round(Height * (AWidth / Width))
end;

procedure T24NSDocumentPage.ResetTimer;
begin
  FTimer.Enabled := False;
  FBlendValue := 0
end;

procedure T24NSDocumentPage.TimerTick(Sender: TObject);
begin
  Inc(FBlendValue, DEF_BLENDING_STEP);
  if FBlendValue >= 255 then
    ResetTimer;
  FViewer.Invalidate
end;

{ T24NSHelperThread }

constructor T24NSHelperThread.Create(AViewer: T24NSPDFViewer);
begin
  inherited Create(False);
  Priority := tpLowest;
  FViewer := AViewer;
  FreeOnTerminate := False
end;

procedure T24NSHelperThread.WaitLooping;
begin
  while not FMessageLoop do
    SwitchToThread
end;

procedure T24NSHelperThread.Execute;
var
  Msg: TMsg;

  function HandleMessage: Boolean; near;

    function NeedHandleMessage: Boolean; near;
    begin
      Result := (Msg.Message >= WM_DONETHREAD)
        and (Msg.Message <= WM_DOWNLOADFILE)
    end;

  begin
    Result := NeedHandleMessage;
    if Result then
      case Msg.Message of
        WM_DONETHREAD:
          Terminate;
        WM_RELEASEBITMAP:
          ReleaseBitmap(Msg);
        WM_RENDERBITMAP:
          RenderBitmap(Msg)
      end
  end;

  function ProcessMessage: Boolean; near;
  begin
    if PeekMessage(Msg, 0, 0, 0, PM_NOREMOVE) then
    begin
      Result := PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
      if Result then
      begin
        if not HandleMessage then
          if not Terminated then
          begin
            TranslateMessage(Msg);
            DispatchMessage(Msg)
          end
      end
    end
    else
      Result := False
  end;

begin
  FMessageLoop := True;
  try
    while not Terminated do
      if not ProcessMessage then
        WaitMessage
  finally
    FMessageLoop := False
  end
end;

procedure T24NSHelperThread.Invalidate;
begin
  if FViewer.Owner is TWinControl then
    TWinControl(FViewer.Owner).Invalidate
end;

procedure T24NSHelperThread.ReleaseBitmap;
begin
  FViewer.Pages.Page(AMsg.wParam).ReleaseBitmap
end;

procedure T24NSHelperThread.RenderBitmap;
begin
  while FViewer.Painting do
    SwitchToThread;
  FViewer.Pages.Page(AMsg.wParam).RenderBitmap(AMsg.lParam)
end;

procedure T24NSHelperThread.Done;
begin
  if not Suspended and not Terminated then
    PostThreadMessage(ThreadID, WM_DONETHREAD, 0, 0)
end;

end.



...
Рейтинг: 0 / 0
22.12.2016, 17:33
    #39373188
Квейд
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Открыть PDF из MemoryStream
Пример

...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Открыть PDF из MemoryStream / 25 сообщений из 104, страница 1 из 5
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]