Qt显示PDF之四pdfium封装
来源:互联网 发布:国外java高并发书籍 编辑:程序博客网 时间:2024/05/16 09:21
如果你已经按照前面的步骤成功生成了库,那么恭喜你。如果没有也不要气馁 ,我后面会放送编译好的库。
我们可以看一下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;
};
#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上使用,后面再介绍
- Qt显示PDF之四pdfium封装
- Qt显示PDF之三 pdfium编译
- Qt显示pdf系列4——封装pdfium库为动态库,显示pdf
- Qt显示pdf系列3——配置编译谷歌开源项目pdfium
- PDFium-PDF开源之旅(2)——运行调试pdfium自带的测试程序
- 基于pdfium获取pdf目录
- Qt显示PDF之二 QAxWidget, QAxWidget
- PDFium-PDF开源之旅(1)-初探代码下载编译
- Qt显示pdf之五在Qt中使用
- Qt之生成pdf
- Qt之生成pdf
- Qt之生成pdf
- qt 之 生成pdf
- Qt显示PDF系列之一
- QT显示机制(四)
- Halcon PDF文档(hdevelop_users_guide)学习总结之四——关于3D显示模式
- Qt之显示图片
- 面对世界竞争对手,如何拿到Google PDF开源项目PDFium?
- RF内置库-----内置库的学习过程总结
- Tomcat源码解析(11)
- laravel使用mews/captcha图片验证码解决方案
- 使用libtiff写RGB彩色tiff图
- 简历项目总结
- Qt显示PDF之四pdfium封装
- Qt 信号-槽的同步与异步处理
- Loss Function的修改启发
- zabbix自动发现network
- 利用插件扩展Qt应用程序
- CODE[VS]1010 过河卒
- jetty servlet容器(转自博客园)
- idea maven项目找不到 mapper.xml sql映射文件问题
- 注释必备