Qt显示PDF之四pdfium封装

xiaoxiao2021-02-28  43

如果你已经按照前面的步骤成功生成了库,那么恭喜你。如果没有也不要气馁 ,我后面会放送编译好的库。

我们可以看一下pdfium的pdfium\build\Debug\lib目录和pdfium\build\Debug\,可以看到其实就一个dll文件和一堆lib。如果使用呢

可以参考pdfium\samples目录下的例子程序。下面我对其进行封装:

首先建立一个win32 dll工程PDFIumReader并引入pdfium头文件和lib目录

并在dllmain函数进行初始化

B#include "stdafx.h" #include "fpdf_ext.h" #include "vld.h" #include "v8.h" #include <iostream> #include <string> void Unsupported_Handler(UNSUPPORT_INFO*, int type) {     std::string feature = "Unknown";     switch (type) {     case FPDF_UNSP_DOC_XFAFORM:         feature = "XFA";         break;     case FPDF_UNSP_DOC_PORTABLECOLLECTION:         feature = "Portfolios_Packages";         break;     case FPDF_UNSP_DOC_ATTACHMENT:     case FPDF_UNSP_ANNOT_ATTACHMENT:         feature = "Attachment";         break;     case FPDF_UNSP_DOC_SECURITY:         feature = "Rights_Management";         break;     case FPDF_UNSP_DOC_SHAREDREVIEW:         feature = "Shared_Review";         break;     case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:     case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:     case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:         feature = "Shared_Form";         break;     case FPDF_UNSP_ANNOT_3DANNOT:         feature = "3D";         break;     case FPDF_UNSP_ANNOT_MOVIE:         feature = "Movie";         break;     case FPDF_UNSP_ANNOT_SOUND:         feature = "Sound";         break;     case FPDF_UNSP_ANNOT_SCREEN_MEDIA:     case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:         feature = "Screen";         break;     case FPDF_UNSP_ANNOT_SIG:         feature = "Digital_Signature";         break;     }     printf("Unsupported feature: %s.\n", feature.c_str()); } BOOL APIENTRY DllMain( HMODULE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved                      ) {     switch (ul_reason_for_call)     {     case DLL_PROCESS_ATTACH:     {         v8::V8::InitializeICU();         FPDF_InitLibrary(NULL);         UNSUPPORT_INFO unsuppored_info;         memset(&unsuppored_info, '\0', sizeof(unsuppored_info));         unsuppored_info.version = 1;         unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler;         FSDK_SetUnSpObjProcessHandler(&unsuppored_info);     }         break;     case DLL_THREAD_ATTACH:         break;     case DLL_THREAD_DETACH:         break;     case DLL_PROCESS_DETACH:         FPDF_DestroyLibrary();         break;     }     return TRUE; }

然后新建一个类PDFIumReaderMgr用于管理多个pdf

头文件:

   PDFIumReaderMgr

#pragma once #include <iostream> #include <map> class PDFIumReader; typedef std::map<std::string, PDFIumReader*> PDFReaders; class PDFIumReaderMgr { public:     static PDFIumReaderMgr *Instance();     bool LoadPDF(const char *name);     void Closepdf(const char *name);     char *LoadPage(const char* filename, int page, float& width, float& height,  bool OutBmp);     int  GetPageCount(const char* filename);     char* GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp);     void SetCurrentPage(const char* filename, int page); private:     PDFIumReaderMgr(){}     ~PDFIumReaderMgr(){} public:     PDFReaders m_pdfReaders;

};

   ------------------------------------------------------------------------------------PDFIumReaderMgr.cpp-----------------------------------------------------------------------------------------------

#include "stdafx.h" #include "PDFReaderMgr.h" #include "PDFIumReader.h" #include <iostream> using namespace std; PDFIumReaderMgr * PDFIumReaderMgr::Instance() {     static PDFIumReaderMgr mgr;     return &mgr; } bool PDFIumReaderMgr::LoadPDF(const char *name) {     if (m_pdfReaders.find(name) != m_pdfReaders.end())     {         std::cout << "this file has loaded" << endl;         return true;     }     PDFIumReader *reader = new PDFIumReader();     m_pdfReaders[name] = reader;     return reader->Reader(name); } void PDFIumReaderMgr::Closepdf(const char *name) {     if (m_pdfReaders.find(name) == m_pdfReaders.end())         return;     m_pdfReaders.find(name)->second->Close();     m_pdfReaders.erase(name); } char * PDFIumReaderMgr::LoadPage(const char* filename, int page, float& width, float& height, bool OutBmp) {     if (m_pdfReaders.find(filename) == m_pdfReaders.end())         return 0;     return m_pdfReaders.find(filename)->second->GetPdfPage(page, width, height, OutBmp); } int PDFIumReaderMgr::GetPageCount(const char* filename) {     if (m_pdfReaders.find(filename) == m_pdfReaders.end())         return 0;     return m_pdfReaders.find(filename)->second->GetPageCount(); } char* PDFIumReaderMgr::GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp) {     if (m_pdfReaders.find(filename) == m_pdfReaders.end())         return 0;     return m_pdfReaders.find(filename)->second->GetNextPage(page, width, height, OutBmp); } void PDFIumReaderMgr::SetCurrentPage(const char* filename, int page) {     if (m_pdfReaders.find(filename) == m_pdfReaders.end())         return ;     m_pdfReaders.find(filename)->second->SetCurrentPage(page); } 最后创建一个真正读取pdf的类PDFIumReader

-------------------------------------------------------------------------PDFIumReader.h-----------------------------------------------------------------------------------------

#pragma once #include "fpdf_dataavail.h" #include "fpdfview.h" #include "fpdfformfill.h" #include "fpdf_dataavail.h" #include "fpdfedit.h" #include "fpdftext.h" #include "fpdfview.h" #include <memory> #include <map> #include <sstream> #include <string> #include <utility> #include <vector> #include <iostream> #include <string> enum ResultType {     PDF_DATA_ERROR = 0,     PDF_DATA_NO_ERROR = 1,     PDF_DATA_NO_DATA = 2 }; enum Output_Type {     OUTPUT_STR,     OUTPUT_BMP }; class PDFIumLoader { public:     PDFIumLoader(){}     PDFIumLoader(const char* pBuf, size_t len);     const char* m_pBuf;     size_t m_Len; }; class PDFIumReader { private:     static void WritePpm(const char* pdf_name, int num, const char* buffer, int stride, int width, int height);     static void AddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size);     static bool IsDataAvail(FX_FILEAVAIL* pThis, size_t offset, size_t size);     static int  GetBlock(void* param, unsigned long pos, unsigned char* pBuf, unsigned long size);     static int  FormAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int); public:     PDFIumReader(){}     ~PDFIumReader();     bool Reader(const char *name);     void Close();     char* GetPdfPage(int pageIndex, float& width, float& height,  bool OutBmp = false);     int GetPageCount(){ return m_nPageCount; }     char* GetNextPage(int &page, float& width, float& height, bool OutBmp);     void SetCurrentPage(int page); private:     void  RenderPdf(const char* pBuf, size_t len); private:     FPDF_DOCUMENT m_pPdfDoc = nullptr;     FPDF_FORMFILLINFO m_formCallbacks;     IPDF_JSPLATFORM m_platformcallbacks;     FPDF_FORMHANDLE m_formHandle;     FX_DOWNLOADHINTS m_hints;     FX_FILEAVAIL m_fileAvail;     FPDF_FILEACCESS m_fileAccess;     PDFIumLoader m_PDFIumLoader;     FPDF_AVAIL m_PdfAvail;     char *m_pdfBuf;     bool m_bIsLinearized = false;     std::string m_strFileName;     int m_nPageCount = 0;     int m_nCurrentPage = 0; };

-------------------------------------------------------------------------------------PDFIumReader.cpp______________________________________________

#include "PDFIumReader.h" using namespace std; void PDFIumReader::RenderPdf(const char* pBuf, size_t len) {     memset(&m_platformcallbacks, '\0', sizeof(m_platformcallbacks));     m_platformcallbacks.version = 1;     m_platformcallbacks.app_alert = FormAlert;     memset(&m_formCallbacks, '\0', sizeof(m_formCallbacks));     m_formCallbacks.version = 1;     m_formCallbacks.m_pJsPlatform = &m_platformcallbacks;     m_PDFIumLoader.m_pBuf = pBuf;     m_PDFIumLoader.m_Len = len;     memset(&m_fileAccess, '\0', sizeof(m_fileAccess));     m_fileAccess.m_FileLen = static_cast<unsigned long>(len);     m_fileAccess.m_GetBlock = GetBlock;     m_fileAccess.m_Param = &m_PDFIumLoader;     memset(&m_fileAvail, '\0', sizeof(m_fileAvail));     m_fileAvail.version = 1;     m_fileAvail.IsDataAvail = IsDataAvail;     memset(&m_hints, '\0', sizeof(m_hints));     m_hints.version = 1;     m_hints.AddSegment = AddSegment;     m_PdfAvail = FPDFAvail_Create(&m_fileAvail, &m_fileAccess);     (void)FPDFAvail_IsDocAvail(m_PdfAvail, &m_hints);     if (!FPDFAvail_IsLinearized(m_PdfAvail)) {         printf("Non-linearized path...\n");         m_pPdfDoc = FPDF_LoadCustomDocument(&m_fileAccess, NULL);     }     else {         printf("Linearized path...\n");         m_pPdfDoc = FPDFAvail_GetDocument(m_PdfAvail, NULL);     }     (void)FPDF_GetDocPermissions(m_pPdfDoc);     (void)FPDFAvail_IsFormAvail(m_PdfAvail, &m_hints);     m_formHandle = FPDFDOC_InitFormFillEnviroument(m_pPdfDoc, &m_formCallbacks);     FPDF_SetFormFieldHighlightColor(m_formHandle, 0, 0xFFE4DD);     FPDF_SetFormFieldHighlightAlpha(m_formHandle, 100);     int first_page = FPDFAvail_GetFirstPageNum(m_pPdfDoc);     FPDFAvail_IsPageAvail(m_PdfAvail, first_page, &m_hints);     m_nPageCount = FPDF_GetPageCount(m_pPdfDoc);     for (int i = 0; i < m_nPageCount; ++i) {         FPDFAvail_IsPageAvail(m_PdfAvail, i, &m_hints);     }     FORM_DoDocumentJSAction(m_formHandle);     FORM_DoDocumentOpenAction(m_formHandle); } void PDFIumReader::WritePpm(const char* pdf_name, int num, const char* buffer, int stride, int width, int height) {     if (stride < 0 || width < 0 || height < 0)         return;     if (height > 0 && width > INT_MAX / height)         return;     int out_len = width * height;     if (out_len > INT_MAX / 3)         return;     out_len *= 3;     char filename[256];     _snprintf(filename, sizeof(filename), "%s.%d.ppm", pdf_name, num);     FILE* fp = fopen(filename, "w");     if (!fp)         return;     fprintf(fp, "P6\n# PDF test render\n%d %d\n255\n", width, height);     // Source data is B, G, R, unused.     // Dest data is R, G, B.     char* result = new char[out_len];     if (result) {         for (int h = 0; h < height; ++h) {             const char* src_line = buffer + (stride * h);             char* dest_line = result + (width * h * 3);             for (int w = 0; w < width; ++w) {                 // R                 dest_line[w * 3] = src_line[(w * 4) + 2];                 // G                 dest_line[(w * 3) + 1] = src_line[(w * 4) + 1];                 // B                 dest_line[(w * 3) + 2] = src_line[w * 4];             }         }         fwrite(result, out_len, 1, fp);         delete[] result;     }     fclose(fp); } void PDFIumReader::AddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {      } bool PDFIumReader::IsDataAvail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {     return true; } int PDFIumReader::GetBlock(void* param, unsigned long pos, unsigned char* pBuf, unsigned long size) {     PDFIumLoader* pLoader = (PDFIumLoader*)param;     if (pos + size < pos || pos + size > pLoader->m_Len) return 0;     memcpy(pBuf, pLoader->m_pBuf + pos, size);     return 1; } int PDFIumReader::FormAlert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) {     printf("Form_Alert called.\n");     return 0; } PDFIumReader::~PDFIumReader() {     Close(); } bool PDFIumReader::Reader(const char *filename) {     if (NULL == filename)         return false;     m_strFileName = filename;     FILE* file = fopen(filename, "rb");     if (!file) {         fprintf(stderr, "Failed to open: %s\n", filename);         return false;     }     (void)fseek(file, 0, SEEK_END);     size_t len = ftell(file);     (void)fseek(file, 0, SEEK_SET);     m_pdfBuf = (char*)malloc(len);     size_t ret = fread(m_pdfBuf, 1, len, file);     (void)fclose(file);     RenderPdf(m_pdfBuf, len);     return true; } char* PDFIumReader::GetPdfPage(int pageIndex, float& width, float& height, bool OutBmp) {     if (pageIndex < 0)         return 0;     pageIndex = min(pageIndex, m_nPageCount - 1);     m_nCurrentPage = pageIndex;     FPDF_PAGE page = FPDF_LoadPage(m_pPdfDoc, pageIndex);     FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page);     FORM_OnAfterLoadPage(page, m_formHandle);     FORM_DoPageAAction(page, m_formHandle, FPDFPAGE_AACTION_OPEN);     width = static_cast<int>(FPDF_GetPageWidth(page));     height = static_cast<int>(FPDF_GetPageHeight(page));     FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);     FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 255, 255, 255, 255);     FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);     FPDF_FFLDraw(m_formHandle, bitmap, page, 0, 0, width, height, 0, 0);     char* buffer = reinterpret_cast<char*>(         FPDFBitmap_GetBuffer(bitmap));     if (OutBmp) {         int stride = FPDFBitmap_GetStride(bitmap);         WritePpm(m_strFileName.c_str(), pageIndex, buffer, stride, width, height);     }     FPDFBitmap_Destroy(bitmap);     FORM_DoPageAAction(page, m_formHandle, FPDFPAGE_AACTION_CLOSE);     FORM_OnBeforeClosePage(page, m_formHandle);     FPDFText_ClosePage(text_page);     FPDF_ClosePage(page);     return buffer; } char* PDFIumReader::GetNextPage(int &page, float& width, float& height, bool OutBmp) {     page = ++m_nCurrentPage;     page = min(page, m_nPageCount - 1);     page = max(0, page);     return GetPdfPage(page, width, height, OutBmp); } void PDFIumReader::SetCurrentPage(int page) {     m_nCurrentPage = page;     m_nCurrentPage = min(m_nCurrentPage, m_nPageCount - 1);     m_nCurrentPage = max(0, m_nCurrentPage); } void PDFIumReader::Close() {     if (!this->m_pPdfDoc)         return;     FORM_DoDocumentAAction(this->m_pPdfDoc, FPDFDOC_AACTION_WC);     FPDFDOC_ExitFormFillEnviroument(this->m_formHandle);     FPDF_CloseDocument(this->m_pPdfDoc);     FPDFAvail_Destroy(this->m_PdfAvail);     free(m_pdfBuf);     this->m_pPdfDoc = NULL; } PDFIumLoader::PDFIumLoader(const char* pBuf, size_t len) : m_pBuf(pBuf), m_Len(len) { }

然后建立导出接口:新建一个PDFIumReaerII.h

加入如下导出接口:

#ifndef _PDF_IUM_READER_H_ #define _PDF_IUM_READER_H_

#ifdef PDF_IUM_READER_API extern "C" _declspec(dllexport)   #else  #define PDF_IUM_READER_API extern "C" _declspec(dllexport)  #endif 

//加载 PDF_IUM_READER_API bool  PDFIumReader_Loadpdf(const char* filename, int length); //关闭  PDF_IUM_READER_API bool  PDFIumReader_Closepdf(const char* filename); //加载某个page PDF_IUM_READER_API char* PDFIumReader_LoadPage(const char* filename, int page, float& width, float& height, int& size, bool OutBmp); //关闭个page PDF_IUM_READER_API void  PDFIumReader_ClosePage(const char* filename, int page); //获取总页数 PDF_IUM_READER_API  int  PDFIumReader_GetPageCount(const char* filename); //获取下一页该渲染的页  PDF_IUM_READER_API int  PDFIumReader_GetNextPage(const char* filename); #endif

最后定义导出函数如下

--------------------------------------------------------------------------PDFIumReaderII.h-----------------------------------------------------------------------------------------------

#ifndef _PDF_IUM_READER_H_ #define _PDF_IUM_READER_H_ #ifdef PDF_IUM_READER_API extern "C" _declspec(dllexport)    #else   #define PDF_IUM_READER_API extern "C" _declspec(dllexport)   #endif   //加载 PDF_IUM_READER_API bool  PDFIumReader_Loadpdf(const char* filename); //关闭  PDF_IUM_READER_API void  PDFIumReader_Closepdf(const char* filename); //加载某个page PDF_IUM_READER_API char* PDFIumReader_GetPage(const char* filename, int page, float& width, float& height, bool OutBmp = false); //获取总页数 PDF_IUM_READER_API  int  PDFIumReader_GetPageCount(const char* filename); //获取下一页该渲染的页 PDF_IUM_READER_API  char*  PDFIumReader_GetNextPage(const char* filename, int &page, float& width, float& height, bool OutBmp =false); //设置当前页 PDF_IUM_READER_API void  PDFIumReader_SetCurrentPage(const char* filename, int page); #endif

--------------------------------------------------------------------PDFIumReaderII.cpp----------------------------------------------------------------------------------------

// PdfIumManager.cpp : 定义 DLL 应用程序的导出函数。 // #include "PDFIumReaderII.h" #include "PDFReaderMgr.h" using namespace std; PDF_IUM_READER_API bool PDFIumReader_Loadpdf(const char* filename) {     return PDFIumReaderMgr::Instance()->LoadPDF(filename); } PDF_IUM_READER_API void  PDFIumReader_Closepdf(const char* filename) {     PDFIumReaderMgr::Instance()->Closepdf(filename); } PDF_IUM_READER_API char*   PDFIumReader_GetPage(const char* filename, int page, float& width, float& height, bool OutBmp) {     return PDFIumReaderMgr::Instance()->LoadPage(filename, page, width, height, OutBmp); } PDF_IUM_READER_API int  PDFIumReader_GetPageCount(const char* filename) {     return PDFIumReaderMgr::Instance()->GetPageCount(filename); } PDF_IUM_READER_API char * PDFIumReader_GetNextPage(const char* filename, int &page, float& width, float& height,  bool OutBmp) {     return PDFIumReaderMgr::Instance()->GetNextPage(filename, page, width, height, OutBmp); } PDF_IUM_READER_API void  PDFIumReader_SetCurrentPage(const char* filename, int page) {     PDFIumReaderMgr::Instance()->SetCurrentPage(filename, page); }

最后引入库 如果编译32为引入32的pdfium库 64的引入64位库

使用:

#include "F:\\Qt-pdf\\PdfIumReader64\\PdfIumManager\\PDFIumReaderII.h" #pragma  comment(lib, "F:\\Work\\Win32Project2\\x64\\Debug\\PDFIumReaderII.lib") int _tmain(int argc, _TCHAR* argv[]) {     PDFIumReader_Loadpdf("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");    int counts = PDFIumReader_GetPageCount("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");    for (int i = 0; i < counts; ++i)    {        float width, height = 0;        int length = 0;        char *buf = PDFIumReader_GetPage("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf", i, width, height,true);    }    PDFIumReader_Closepdf("F:\\Work\\Win32Project2\\x64\\Debug\\1.pdf");    getchar();     return 0; }

这里返回的是char类型的数据,可以直接在vc和Qt上使用,后面再介绍


转载请注明原文地址: https://www.6miu.com/read-83230.html

最新回复(0)