环境搭建:
1、mupdf-1.17.0-source库。mupdf-1.17.0-source默认是VS2019的工程,由于示例用的是VS2017,所以需要用VS2017重新编译mupdf-1.17.0-source工程,生成LIB库文件。
2、vs2017+QT5.14.2
3、mupdf-1.17.0-source库的位置 https://download.csdn.net/download/C_panpan/88157816https://download.csdn.net/download/C_panpan/88157816
示例代码:
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_pdfDemo.h"
class pdfDemo : public QMainWindow
{
Q_OBJECT
public:
pdfDemo(QWidget *parent = nullptr);
~pdfDemo();
bool PDF2PNG(std::string pdfFilePath, int pdfPageIdx, std::string outputPNGFilePath);
bool loadTxt(std::string pdfFilePath, int pdfPageIdx, std::string outputPNGFilePath);
private slots:
void OnNextPage();
private:
Ui::pdfDemoClass ui;
int m_ipage;
};
#include "pdfDemo.h"
#include "mupdf/fitz.h"
#include "mupdf/pdf.h"
#include <QLabel>
bool pdfDemo::PDF2PNG(std::string pdfFilePath, int pdfPageIdx, std::string outputPNGFilePath)
{
if (pdfFilePath.empty() || pdfPageIdx < 0)
{
return false;
}
//使用默认值
int pageCount = 0;
float zoom = 100;
float rotate = 0;
fz_context *ctx;
fz_document *doc;
fz_pixmap *pix;
fz_matrix ctm;
fz_stext_page *text;
int x, y;
/* Create a context to hold the exception stack and various caches. */
ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED);
if (!ctx)
{
fprintf(stderr, "cannot create mupdf context\n");
return false;
}
/* Register the default file types to handle. */
fz_try(ctx)
{
fz_register_document_handlers(ctx);
}
fz_catch(ctx)
{
fprintf(stderr, "cannot register document handlers: %s\n", fz_caught_message(ctx));
fz_drop_context(ctx);
return false;
}
/* Open the document. */
fz_try(ctx)
{
doc = fz_open_document(ctx, pdfFilePath.c_str());
}
fz_catch(ctx)
{
fprintf(stderr, "cannot open document: %s\n", fz_caught_message(ctx));
fz_drop_context(ctx);
return false;
}
/* Count the number of pages. */
fz_try(ctx)
{
pageCount = fz_count_pages(ctx, doc);
}
fz_catch(ctx)
{
fprintf(stderr, "cannot count number of pages: %s\n", fz_caught_message(ctx));
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return false;
}
if (pdfPageIdx < 0 || pdfPageIdx >= pageCount)
{
fprintf(stderr, "page number out of range: %d (page count %d)\n", pdfPageIdx + 1, pageCount);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return false;
}
/* Compute a transformation matrix for the zoom and rotation desired. */
/* The default resolution without scaling is 72 dpi. */
ctm = fz_scale(zoom / 100, zoom / 100);
ctm = fz_pre_rotate(ctm, rotate);
/* Render page to an RGB pixmap. */
fz_buffer *bu;
fz_try(ctx)
{
pix = fz_new_pixmap_from_page_number(ctx, doc, pdfPageIdx, ctm, fz_device_rgb(ctx), 0);
//提取PDF中的文字
fz_page *page = pdf_load_page_imp(ctx, doc, 0, pdfPageIdx);
const fz_stext_options opts = { FZ_STEXT_PRESERVE_IMAGES };
text = fz_new_stext_page_from_page(ctx, page, &opts);
bu = fz_new_buffer_from_stext_page(ctx, text);
//中文乱码
QString str = QString::fromLocal8Bit(reinterpret_cast<const char*>(bu->data));
//中文不会乱码
std::string str1 = (char*)bu->data;
QString sstr = QString::fromStdString(str1);
ui.label_2->setText(sstr);
}
fz_catch(ctx)
{
fprintf(stderr, "cannot render page: %s\n", fz_caught_message(ctx));
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return false;
}
fz_try(ctx)
{
//保存为PNG图片
fz_save_pixmap_as_png(ctx, pix, outputPNGFilePath.c_str());
//渲染成图片
// 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, pix->stride, QImage::Format_RGB888);
// QLabel *label = new QLabel;
ui.label->setPixmap(QPixmap::fromImage(image));
//ui.stackedWidget->addWidget(label);
//ui.stackedWidget->setCurrentIndex(0);
}
fz_catch(ctx)
{
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return false;
}
/* Clean up. */
fz_drop_pixmap(ctx, pix);
fz_drop_document(ctx, doc);
fz_drop_context(ctx);
return true;
}
bool pdfDemo::loadTxt(std::string pdfFilePath, int pdfPageIdx, std::string outputPNGFilePath)
{
return false;
}
pdfDemo::pdfDemo(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
connect(ui.btnNext, SIGNAL(clicked()), this, SLOT(OnNextPage()));
m_ipage = 0;
OnNextPage();
}
pdfDemo::~pdfDemo()
{}
void pdfDemo::OnNextPage()
{
std::string pdfFilePath = "1.pdf";
std::string outputFilePath = "a.png";
bool isOk = PDF2PNG(pdfFilePath, m_ipage, outputFilePath);
m_ipage++;
}
运行效果