163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			163 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								## 前言
							 | 
						|||
| 
								 | 
							
								最近有个pdf的需求,Qt竟然没有显示pdf的api,着实令人郁闷。之后我尝试用了poppler,但是光配置编译工程就相当麻烦了,没有cmake等开源项目编译经验的人完全一脸懵逼。PDFium也是同理(手头上没有vpn也无法尝试)。感觉Mupdf编译器起来比较简单,所以就来用了一下。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								本人使用的版本是Mupdf1.12.0+Qt5.9.3+vs2015
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 下载Mupdf库
							 | 
						|||
| 
								 | 
							
								https://mupdf.com/downloads/
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 编译Mupdf
							 | 
						|||
| 
								 | 
							
								在mupdf-1.12.0-source\platform\win32目录下就有现成的mupdf.sln。
							 | 
						|||
| 
								 | 
							
								这里需要注意:这个工程默认使用的是/MT,而Qt MSVC默认用的是/MD,所以需要修改编译工程设置。我们这里只需要在编译工程中修改就可以了。
							 | 
						|||
| 
								 | 
							
								以下是一些有关QMake中设置运行库属性 /md /md /mt /mtd 的相关参考
							 | 
						|||
| 
								 | 
							
								- http://blog.csdn.net/caoshangpa/article/details/51416077
							 | 
						|||
| 
								 | 
							
								- http://www.cnblogs.com/codingmylife/archive/2010/05/08/1730832.html
							 | 
						|||
| 
								 | 
							
								- http://www.voidcn.com/article/p-hhosrsia-hq.html
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								工程里默认生成的是都是静态库,请注意!根据测试需要的分别是libmupdf.lib、libresources.lib、libthirdparty.lib这三个库(只使用了docs\examples\example.c的代码,使用别的函数可能需要再编译别的工程)
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								分别修改解决方案中的libmupdf、libthirdparty、libresources这三个工程,将debug下改成/MDd,release下改成/MD,编译即可得到这3个文件。其中libresources只有release版本的,所以debug模式下,我也引用这个文件。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 在Qt工程中引入Mupdf静态库
							 | 
						|||
| 
								 | 
							
								- 引入lib文件
							 | 
						|||
| 
								 | 
							
									- 新建一个工程,在工程的图标上右键——添加库——外部库。平台只勾选windows,链接选择静态,之后选择对应的库就可以了。(本人将debug与release编译的分别放在debug与release文件夹中)
							 | 
						|||
| 
								 | 
							
								- 添加包含目录
							 | 
						|||
| 
								 | 
							
									- 将Mupdf目录中的include复制到工程目录下(本人又新建了一个mupdf,将所有文件都放在里面了)
							 | 
						|||
| 
								 | 
							
									- 本人是这么写的,具体可以参考源代码:
							 | 
						|||
| 
								 | 
							
									- `INCLUDEPATH += $$PWD/mupdf/include/`
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								之后运行QMake。
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 编写代码进行测试
							 | 
						|||
| 
								 | 
							
								```c++
							 | 
						|||
| 
								 | 
							
								#include "widget.h"
							 | 
						|||
| 
								 | 
							
								#include "ui_widget.h"
							 | 
						|||
| 
								 | 
							
								#include <QMessageBox>
							 | 
						|||
| 
								 | 
							
								#include <QDebug>
							 | 
						|||
| 
								 | 
							
								#include <QImage>
							 | 
						|||
| 
								 | 
							
								#include <QPixmap>
							 | 
						|||
| 
								 | 
							
								#include <QLabel>
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								#include "mupdf/fitz.h"
							 | 
						|||
| 
								 | 
							
								#include "mupdf/pdf.h"
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								Widget::Widget(QWidget *parent) :
							 | 
						|||
| 
								 | 
							
								    QWidget(parent),
							 | 
						|||
| 
								 | 
							
								    ui(new Ui::Widget)
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    ui->setupUi(this);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    char *input = const_cast< char* >("document.pdf");
							 | 
						|||
| 
								 | 
							
								    float zoom, rotate;
							 | 
						|||
| 
								 | 
							
								    int page_number, page_count;
							 | 
						|||
| 
								 | 
							
								    fz_context *ctx;
							 | 
						|||
| 
								 | 
							
								    fz_document *doc;
							 | 
						|||
| 
								 | 
							
								    fz_pixmap *pix;
							 | 
						|||
| 
								 | 
							
								    fz_matrix ctm;
							 | 
						|||
| 
								 | 
							
								    int x, y;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //第一页为0
							 | 
						|||
| 
								 | 
							
								    page_number=1;
							 | 
						|||
| 
								 | 
							
								    //100%缩放比
							 | 
						|||
| 
								 | 
							
								    zoom=100;
							 | 
						|||
| 
								 | 
							
								    //旋转为0
							 | 
						|||
| 
								 | 
							
								    rotate=0;
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //创建上下文
							 | 
						|||
| 
								 | 
							
								    ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
							 | 
						|||
| 
								 | 
							
								    if (!ctx)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<<"cannot create mupdf context";
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //注册文档控制
							 | 
						|||
| 
								 | 
							
								    fz_try(ctx)
							 | 
						|||
| 
								 | 
							
										fz_register_document_handlers(ctx);
							 | 
						|||
| 
								 | 
							
								    fz_catch(ctx)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<<"cannot register document handlers:"<< fz_caught_message(ctx);
							 | 
						|||
| 
								 | 
							
								        fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //打开文档
							 | 
						|||
| 
								 | 
							
								    fz_try(ctx)
							 | 
						|||
| 
								 | 
							
								        doc = fz_open_document(ctx, input);
							 | 
						|||
| 
								 | 
							
								    fz_catch(ctx)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<< "cannot open document:"<< fz_caught_message(ctx);
							 | 
						|||
| 
								 | 
							
								        fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //取得总的页数
							 | 
						|||
| 
								 | 
							
								    fz_try(ctx)
							 | 
						|||
| 
								 | 
							
								        page_count = fz_count_pages(ctx, doc);
							 | 
						|||
| 
								 | 
							
								    fz_catch(ctx)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<< "cannot count number of pages:"<< fz_caught_message(ctx);
							 | 
						|||
| 
								 | 
							
								        fz_drop_document(ctx, doc);
							 | 
						|||
| 
								 | 
							
								        fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    if (page_number < 0 || page_number >= page_count)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<< "page number out of range: "<< page_number + 1<<"page count:"<<page_count;
							 | 
						|||
| 
								 | 
							
								        fz_drop_document(ctx, doc);
							 | 
						|||
| 
								 | 
							
								        fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //计算缩放以及旋转
							 | 
						|||
| 
								 | 
							
								    fz_scale(&ctm, zoom / 100, zoom / 100);
							 | 
						|||
| 
								 | 
							
								    fz_pre_rotate(&ctm, rotate);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //渲染pixmap
							 | 
						|||
| 
								 | 
							
								    fz_try(ctx)
							 | 
						|||
| 
								 | 
							
								        pix = fz_new_pixmap_from_page_number(ctx, doc, page_number, &ctm, fz_device_rgb(ctx), 0);
							 | 
						|||
| 
								 | 
							
								    fz_catch(ctx)
							 | 
						|||
| 
								 | 
							
								    {
							 | 
						|||
| 
								 | 
							
								        qDebug()<<stderr<< "cannot render page: %s\n"<< fz_caught_message(ctx);
							 | 
						|||
| 
								 | 
							
								        fz_drop_document(ctx, doc);
							 | 
						|||
| 
								 | 
							
								        fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								        return;
							 | 
						|||
| 
								 | 
							
								    }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //渲染成图片
							 | 
						|||
| 
								 | 
							
								//   unsigned char *samples = fz_pixmap_samples(ctx, pix);
							 | 
						|||
| 
								 | 
							
								   unsigned char *samples = pix->samples;
							 | 
						|||
| 
								 | 
							
								   int width = fz_pixmap_width(ctx, pix);
							 | 
						|||
| 
								 | 
							
								   int height = fz_pixmap_height(ctx, pix);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								   QImage image(samples, width, height,QImage::Format_RGB888);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								   QLabel *label=new QLabel;
							 | 
						|||
| 
								 | 
							
								   label->setPixmap(QPixmap::fromImage(image));
							 | 
						|||
| 
								 | 
							
								   ui->layout->addWidget(label);
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								//   if (!image.save("a.png")) {
							 | 
						|||
| 
								 | 
							
								//       return;
							 | 
						|||
| 
								 | 
							
								//   }
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								    //回收内存
							 | 
						|||
| 
								 | 
							
								    fz_drop_pixmap(ctx, pix);
							 | 
						|||
| 
								 | 
							
								    fz_drop_document(ctx, doc);
							 | 
						|||
| 
								 | 
							
								    fz_drop_context(ctx);
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								Widget::~Widget()
							 | 
						|||
| 
								 | 
							
								{
							 | 
						|||
| 
								 | 
							
								    delete ui;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								```
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								## 参考代码 
							 | 
						|||
| 
								 | 
							
								https://github.com/blueroseslol/QtMupdf
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								找到一个之前有人封装的库,不过经过测试是无法成功编译的,不过可以参考一下mupdf库的用法。
							 | 
						|||
| 
								 | 
							
								https://github.com/xiangxw/mupdf-qt
							 | 
						|||
| 
								 | 
							
								
							 | 
						|||
| 
								 | 
							
								别的参考:
							 | 
						|||
| 
								 | 
							
								http://blog.csdn.net/chenyijun/article/details/42582977
							 |