admin管理员组文章数量:1621121
上一篇讲了基于poppler库的PDF阅读器的开发,这一篇来讲基于mupdf的PDF阅读器的开发。
在上一篇的篇尾我有附效果图,可以很明显的看出来这个效果是非常差的,网络上有童鞋同样遇到了这个问题,并且做了修正,但是,经过测试完全没用(也可能是版本的问题),所以我不得不做新的尝试。
-
基于mupdf的PDF阅读器
同样的,先要去下载源码,进行解压编译。mupdf库比较好的一点是可以很简单地配置,从而简化很多不需要的库,比如我仅仅是需要提取每一个page,然后放大缩小,上一页、下一页这种操作,而且是在Qt下做的开发,所以很多库就不要了,我的配置如下:
make HAVE_X11=no HAVE_GLUT=no prefix=./out install
三十秒不到的时间就编译完成了,然后在Qt项目中配置库和头文件就可以进行开发了。在安装目录中有一个例子,可以做参考的,可能因为版本问题,例子没有编过,然而这不是很大的问题,稍作修改就可以了。
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QLabel>
#include <QMouseEvent>
#include <QScrollArea>
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
#include <QPointF>
#define Max_abs 20
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void mouseMoveEvent(QMouseEvent *event);
void touchEvent(QTouchEvent *event);
void mousePressEvent(QMouseEvent *event);
private:
float bestFitScale(int pageW, int pageH);
void updatePage();
void fz_print_outline(fz_context *ctx, fz_output *out, fz_outline *outline, int level);
private:
QLabel* label;
float scale;
int page_number;
int page_count;
float zoom, rotate;
//
fz_context *ctx;
fz_document *doc;
fz_pixmap *pix;
QPointF Press_point;
public slots:
void onPrev();
void onNext();
void onZoomIn();
void onZoomOut();
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include <QDebug>
#include <QPushButton>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
page_number=0;//第一页为0
//100%缩放比
zoom=1;
//旋转为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, "Boost程序库完全开发指南深入C++准标准库.pdf");
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;
}
qDebug() << "page_count: "<< page_count;
//get outline
fz_outline *outline = fz_load_outline(ctx, (fz_document*)doc);
fz_try(ctx)
fz_print_outline(ctx, fz_stderr(ctx), outline, 0);
fz_always(ctx)
fz_drop_outline(ctx, outline);
fz_catch(ctx)
fz_rethrow(ctx);
QScrollArea *LogoArea = new QScrollArea(this);
//LogoArea->setGeometry(0, 0, width(), height());
LogoArea->setGeometry(0, 0, 1024, 600);
LogoArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
LogoArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//QWidget *w = new QWidget(LogoArea);
//LogoArea->setWidget(w);
//QScrollBar* vertScrollBar = LogoArea->verticalScrollBar();
label=new QLabel(this);
label->setVisible(false);
LogoArea->setWidget(label);
LogoArea->setAlignment(Qt::AlignCenter);
QPushButton* prevBtn = new QPushButton(this);
prevBtn->setText("Prev");
prevBtn->setGeometry(910, 240, 60,100);
connect(prevBtn, SIGNAL(pressed()), this, SLOT(onPrev()));
QPushButton* nextBtn = new QPushButton(this);
nextBtn->setText("Next");
nextBtn->setGeometry(910, 340, 60,100);
connect( nextBtn, SIGNAL(pressed()), this, SLOT(onNext()));
QPushButton* plusBtn = new QPushButton(this);
plusBtn->setText("+");
plusBtn->setGeometry(910, 50, 20, 20);
connect( plusBtn, SIGNAL(pressed()), this, SLOT(onZoomIn()));
QPushButton* minBtn = new QPushButton(this);
minBtn->setText("-");
minBtn->setGeometry(940, 50, 20, 20);
connect( minBtn, SIGNAL(pressed()), this, SLOT(onZoomOut()));
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;
}
//计算缩放以及旋转
updatePage();
}
Widget::~Widget()
{
}
void Widget::mouseMoveEvent(QMouseEvent *event)
{
qDebug() << event;
int xMove;
int yMove;
xMove = Press_point.x() - event->localPos().x();
yMove = Press_point.y() - event->localPos().y();
event->accept();
}
void Widget::mousePressEvent(QMouseEvent *event)
{
Press_point = event->localPos();
}
void Widget::touchEvent(QTouchEvent *event)
{
qDebug() << event;
}
float Widget::bestFitScale(int pageW, int pageH)
{
return ((width() / pageW) > (height() / pageH) ? (height() / pageH) : (width() / pageW));
}
void Widget::updatePage()
{
fz_matrix ctm = fz_scale( zoom, zoom);
fz_pre_rotate(ctm, rotate);
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 = pix->samples;
int width = fz_pixmap_width(ctx, pix);
int height = fz_pixmap_height(ctx, pix);
qDebug() << "width: "<<width;
qDebug() << "height: "<<height;
label->setGeometry(0,0,width,height);
label->setAlignment(Qt::AlignCenter);
QImage image(samples, width, height,pix->stride,QImage::Format_RGB888);
label->setPixmap(QPixmap::fromImage(image));
label->setVisible(true);
fz_drop_pixmap(ctx, pix);
update();
}
void Widget::onPrev()
{
qDebug() << "onPrev";
page_number--;
if(page_number <= 0)
page_number = 0;
updatePage();
}
void Widget::onNext()
{
qDebug() << "onNext";
page_number++;
if(page_number >= page_count -1)
page_number = page_count -1;
updatePage();
}
void Widget::onZoomIn()
{
zoom += 0.05;
updatePage();
}
void Widget::onZoomOut()
{
zoom -= 0.05;
updatePage();
}
//Tools
void Widget::fz_print_outline(fz_context *ctx, fz_output *out, fz_outline *outline, int level)
{
int i;
if(outline == NULL)
qDebug()<< "outline is NULL!";
while (outline)
{
for (i = 0; i < level; i++)
// fz_write_printf(ctx, out, "\t");
//fz_write_printf(ctx, out, "%s\t%s\n", outline->title, outline->uri);
qDebug()<< outline->title<<" " << outline->uri;
if (outline->down)
fz_print_outline(ctx, out, outline->down, level + 1);
outline = outline->next;
}
}
效果图
这个显示的效果是相当令人满意的。之前有网友说poppler不能满足性能,确实如此。
版权声明:本文标题:基于mupdf的PDF阅读器 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/xitong/1728836596a1176100.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论